Skip to content

Commit 8135672

Browse files
SCRIPTING: Support BucketAggScript return null (#32811) (#32833)
* As explained in #32790, `BucketAggregationScript` must support `null` as a return value * Closes #32790
1 parent 231d916 commit 8135672

File tree

5 files changed

+47
-9
lines changed

5 files changed

+47
-9
lines changed

modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ private static BucketAggregationScript.Factory newBucketAggregationScriptFactory
147147
}
148148
return new BucketAggregationScript(parameters) {
149149
@Override
150-
public double execute() {
150+
public Double execute() {
151151
getParams().forEach((name, value) -> {
152152
ReplaceableConstDoubleValues placeholder = functionValuesMap.get(name);
153153
if (placeholder == null) {

server/src/main/java/org/elasticsearch/script/BucketAggregationScript.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public Map<String, Object> getParams() {
4646
return params;
4747
}
4848

49-
public abstract double execute();
49+
public abstract Double execute();
5050

5151
public interface Factory {
5252
BucketAggregationScript newInstance(Map<String, Object> params);

server/src/main/java/org/elasticsearch/search/aggregations/pipeline/bucketscript/BucketScriptPipelineAggregator.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,17 @@ public InternalAggregation reduce(InternalAggregation aggregation, ReduceContext
110110
if (skipBucket) {
111111
newBuckets.add(bucket);
112112
} else {
113-
double returned = factory.newInstance(vars).execute();
114-
final List<InternalAggregation> aggs = StreamSupport.stream(bucket.getAggregations().spliterator(), false).map(
113+
Double returned = factory.newInstance(vars).execute();
114+
if (returned == null) {
115+
newBuckets.add(bucket);
116+
} else {
117+
final List<InternalAggregation> aggs = StreamSupport.stream(bucket.getAggregations().spliterator(), false).map(
115118
(p) -> (InternalAggregation) p).collect(Collectors.toList());
116-
aggs.add(new InternalSimpleValue(name(), returned, formatter, new ArrayList<>(), metaData()));
117-
InternalMultiBucketAggregation.InternalBucket newBucket = originalAgg.createBucket(new InternalAggregations(aggs),
119+
aggs.add(new InternalSimpleValue(name(), returned, formatter, new ArrayList<>(), metaData()));
120+
InternalMultiBucketAggregation.InternalBucket newBucket = originalAgg.createBucket(new InternalAggregations(aggs),
118121
bucket);
119-
newBuckets.add(newBucket);
122+
newBuckets.add(newBucket);
123+
}
120124
}
121125
}
122126
return originalAgg.create(newBuckets);

server/src/test/java/org/elasticsearch/search/aggregations/pipeline/BucketScriptIT.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ protected Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
117117
return value0 + value1 + value2;
118118
});
119119

120+
scripts.put("return null", vars -> null);
121+
120122
return scripts;
121123
}
122124
}
@@ -478,6 +480,33 @@ public void testInlineScriptInsertZeros() {
478480
}
479481
}
480482

483+
public void testInlineScriptReturnNull() {
484+
SearchResponse response = client()
485+
.prepareSearch("idx")
486+
.addAggregation(
487+
histogram("histo")
488+
.field(FIELD_1_NAME).interval(interval)
489+
.subAggregation(
490+
bucketScript(
491+
"nullField",
492+
new Script(ScriptType.INLINE, CustomScriptPlugin.NAME, "return null", Collections.emptyMap())
493+
)
494+
)
495+
).execute().actionGet();
496+
497+
assertSearchResponse(response);
498+
499+
Histogram histo = response.getAggregations().get("histo");
500+
assertThat(histo, notNullValue());
501+
assertThat(histo.getName(), equalTo("histo"));
502+
List<? extends Histogram.Bucket> buckets = histo.getBuckets();
503+
504+
for (int i = 0; i < buckets.size(); ++i) {
505+
Histogram.Bucket bucket = buckets.get(i);
506+
assertNull(bucket.getAggregations().get("nullField"));
507+
}
508+
}
509+
481510
public void testStoredScript() {
482511
assertAcked(client().admin().cluster().preparePutStoredScript()
483512
.setId("my_script")

test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,13 @@ public void execute(Map<String, Object> ctx) {
111111
} else if (context.instanceClazz.equals(BucketAggregationScript.class)) {
112112
BucketAggregationScript.Factory factory = parameters -> new BucketAggregationScript(parameters) {
113113
@Override
114-
public double execute() {
115-
return ((Number) script.apply(getParams())).doubleValue();
114+
public Double execute() {
115+
Object ret = script.apply(getParams());
116+
if (ret == null) {
117+
return null;
118+
} else {
119+
return ((Number) ret).doubleValue();
120+
}
116121
}
117122
};
118123
return context.factoryClazz.cast(factory);

0 commit comments

Comments
 (0)