diff --git a/modules/aggs-matrix-stats/src/main/java/org/elasticsearch/search/aggregations/matrix/stats/InternalMatrixStats.java b/modules/aggs-matrix-stats/src/main/java/org/elasticsearch/search/aggregations/matrix/stats/InternalMatrixStats.java index e6def911c209e..94b571635cff9 100644 --- a/modules/aggs-matrix-stats/src/main/java/org/elasticsearch/search/aggregations/matrix/stats/InternalMatrixStats.java +++ b/modules/aggs-matrix-stats/src/main/java/org/elasticsearch/search/aggregations/matrix/stats/InternalMatrixStats.java @@ -254,6 +254,11 @@ public InternalAggregation reduce(List aggregations, Reduce return new InternalMatrixStats(name, runningStats.docCount, runningStats, null, getMetadata()); } + @Override + protected boolean mustReduceOnSingleInternalAgg() { + return true; + } + @Override public int hashCode() { return Objects.hash(super.hashCode(), stats, results); diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/InternalAggregation.java b/server/src/main/java/org/elasticsearch/search/aggregations/InternalAggregation.java index f09ebe5c20c28..035caf825ff2c 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/InternalAggregation.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/InternalAggregation.java @@ -223,9 +223,17 @@ public InternalAggregation reducePipelines( * aggregations are of the same type (the same type as this aggregation). For best efficiency, when implementing, * try reusing an existing instance (typically the first in the given list) to save on redundant object * construction. + * + * @see #mustReduceOnSingleInternalAgg() */ public abstract InternalAggregation reduce(List aggregations, ReduceContext reduceContext); + /** + * Signal the framework if the {@linkplain InternalAggregation#reduce(List, ReduceContext)} phase needs to be called + * when there is only one {@linkplain InternalAggregation}. + */ + protected abstract boolean mustReduceOnSingleInternalAgg(); + /** * Return true if this aggregation is mapped, and can lead a reduction. If this agg returns * false, it should return itself if asked to lead a reduction diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/InternalAggregations.java b/server/src/main/java/org/elasticsearch/search/aggregations/InternalAggregations.java index f5812576da8ed..cbaaded21db5a 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/InternalAggregations.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/InternalAggregations.java @@ -161,7 +161,12 @@ public static InternalAggregations reduce(List aggregation // If all aggs are unmapped, the agg that leads the reduction will just return itself aggregations.sort(INTERNAL_AGG_COMPARATOR); InternalAggregation first = aggregations.get(0); // the list can't be empty as it's created on demand - reducedAggregations.add(first.reduce(aggregations, context)); + if (first.mustReduceOnSingleInternalAgg() || aggregations.size() > 1) { + reducedAggregations.add(first.reduce(aggregations, context)); + } else { + // no need for reduce phase + reducedAggregations.add(first); + } } return from(reducedAggregations); diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/InternalMultiBucketAggregation.java b/server/src/main/java/org/elasticsearch/search/aggregations/InternalMultiBucketAggregation.java index a7333f124a4ea..958572bda783f 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/InternalMultiBucketAggregation.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/InternalMultiBucketAggregation.java @@ -177,6 +177,11 @@ public InternalAggregation copyWithRewritenBuckets(Function consumer) { for (B bucket : getBuckets()) { diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/InternalSingleBucketAggregation.java b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/InternalSingleBucketAggregation.java index ff5eaa33661f4..1b23c0058c897 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/InternalSingleBucketAggregation.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/InternalSingleBucketAggregation.java @@ -176,6 +176,11 @@ public final double sortValue(AggregationPath.PathElement head, Iterator rewriter) { InternalAggregations rewritten = rewriter.apply(aggregations); diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalGeoBounds.java b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalGeoBounds.java index c1828b6ab9739..bddcc4d4bc5a5 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalGeoBounds.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalGeoBounds.java @@ -116,6 +116,11 @@ public InternalAggregation reduce(List aggregations, Reduce return new InternalGeoBounds(name, top, bottom, posLeft, posRight, negLeft, negRight, wrapLongitude, getMetadata()); } + @Override + protected boolean mustReduceOnSingleInternalAgg() { + return false; + } + @Override public Object getProperty(List path) { if (path.isEmpty()) { diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalGeoCentroid.java b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalGeoCentroid.java index a2ad659cfe17c..115a13c9b3ae4 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalGeoCentroid.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalGeoCentroid.java @@ -133,6 +133,11 @@ public InternalGeoCentroid reduce(List aggregations, Reduce return new InternalGeoCentroid(name, result, totalCount, getMetadata()); } + @Override + protected boolean mustReduceOnSingleInternalAgg() { + return false; + } + @Override public Object getProperty(List path) { if (path.isEmpty()) { diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalNumericMetricsAggregation.java b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalNumericMetricsAggregation.java index d82289b7b0c17..50c981a9bddbc 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalNumericMetricsAggregation.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalNumericMetricsAggregation.java @@ -128,6 +128,11 @@ public final double sortValue(AggregationPath.PathElement head, Iterator" + head + "]"); } + @Override + protected boolean mustReduceOnSingleInternalAgg() { + return false; + } + @Override public int hashCode() { return Objects.hash(super.hashCode(), format); diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalScriptedMetric.java b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalScriptedMetric.java index 0b78b70ed7679..f51697f126d75 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalScriptedMetric.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalScriptedMetric.java @@ -74,7 +74,7 @@ protected void doWriteTo(StreamOutput out) throws IOException { /* * I *believe* that this situation can only happen in cross * cluster search right now. Thus the message. But computers - * are hard. + * are hard. */ throw new IllegalArgumentException("scripted_metric doesn't support cross cluster search until 7.8.0"); } @@ -134,6 +134,11 @@ public InternalAggregation reduce(List aggregations, Reduce return new InternalScriptedMetric(firstAggregation.getName(), aggregation, firstAggregation.reduceScript, getMetadata()); } + @Override + protected boolean mustReduceOnSingleInternalAgg() { + return true; + } + @Override public Object getProperty(List path) { if (path.isEmpty()) { diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalTopHits.java b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalTopHits.java index 4f7b4824ba7fd..c268e5a88855d 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalTopHits.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/InternalTopHits.java @@ -41,7 +41,8 @@ /** * Results of the {@link TopHitsAggregator}. */ -public class InternalTopHits extends InternalAggregation implements TopHits { +public class +InternalTopHits extends InternalAggregation implements TopHits { private int from; private int size; private TopDocsAndMaxScore topDocs; @@ -162,6 +163,11 @@ public InternalAggregation reduce(List aggregations, Reduce new SearchHits(hits, reducedTopDocs.totalHits, maxScore), getMetadata()); } + @Override + protected boolean mustReduceOnSingleInternalAgg() { + return true; + } + @Override public Object getProperty(List path) { if (path.isEmpty()) { diff --git a/server/src/test/java/org/elasticsearch/action/search/SearchPhaseControllerTests.java b/server/src/test/java/org/elasticsearch/action/search/SearchPhaseControllerTests.java index 5e635491ce602..e3d1271e8466d 100644 --- a/server/src/test/java/org/elasticsearch/action/search/SearchPhaseControllerTests.java +++ b/server/src/test/java/org/elasticsearch/action/search/SearchPhaseControllerTests.java @@ -1006,6 +1006,11 @@ public InternalAggregation reduce(List aggregations, Reduce return new InternalThrowing(name, false, metadata); } + @Override + protected boolean mustReduceOnSingleInternalAgg() { + return true; + } + @Override public Object getProperty(List path) { return null; diff --git a/test/framework/src/main/java/org/elasticsearch/search/aggregations/AggregatorTestCase.java b/test/framework/src/main/java/org/elasticsearch/search/aggregations/AggregatorTestCase.java index 7ff55fc27a4f5..615fcfd409f91 100644 --- a/test/framework/src/main/java/org/elasticsearch/search/aggregations/AggregatorTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/search/aggregations/AggregatorTestCase.java @@ -991,6 +991,11 @@ public InternalAggregation reduce(List aggregations, Reduce return new InternalAggCardinality(name, cardinality, metadata); } + @Override + protected boolean mustReduceOnSingleInternalAgg() { + return true; + } + @Override public XContentBuilder doXContentBody(XContentBuilder builder, Params params) throws IOException { return builder.array("cardinality", cardinality); diff --git a/x-pack/plugin/analytics/src/main/java/org/elasticsearch/xpack/analytics/stringstats/InternalStringStats.java b/x-pack/plugin/analytics/src/main/java/org/elasticsearch/xpack/analytics/stringstats/InternalStringStats.java index 0d4cabd0a427a..8c7e3e19cd706 100644 --- a/x-pack/plugin/analytics/src/main/java/org/elasticsearch/xpack/analytics/stringstats/InternalStringStats.java +++ b/x-pack/plugin/analytics/src/main/java/org/elasticsearch/xpack/analytics/stringstats/InternalStringStats.java @@ -214,6 +214,11 @@ public InternalStringStats reduce(List aggregations, Reduce showDistribution, format, getMetadata()); } + @Override + protected boolean mustReduceOnSingleInternalAgg() { + return false; + } + @Override public Object getProperty(List path) { if (path.isEmpty()) { diff --git a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/aggs/InternalInferenceAggregation.java b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/aggs/InternalInferenceAggregation.java index 867872b682f8a..bf79901dbb77c 100644 --- a/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/aggs/InternalInferenceAggregation.java +++ b/x-pack/plugin/ml/src/main/java/org/elasticsearch/xpack/ml/inference/aggs/InternalInferenceAggregation.java @@ -18,7 +18,7 @@ import java.util.Map; import java.util.Objects; -public class InternalInferenceAggregation extends InternalAggregation { +public class InternalInferenceAggregation extends InternalAggregation { private final InferenceResults inferenceResult; @@ -47,6 +47,10 @@ public InternalAggregation reduce(List aggregations, Reduce throw new UnsupportedOperationException("Reducing an inference aggregation is not supported"); } + @Override + protected boolean mustReduceOnSingleInternalAgg() { + return true; + } @Override public Object getProperty(List path) { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/TestSingleValueAggregation.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/TestSingleValueAggregation.java index 9cfe392bb5df8..b89301a69edce 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/TestSingleValueAggregation.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/TestSingleValueAggregation.java @@ -40,6 +40,11 @@ public InternalAggregation reduce(List aggregations, Reduce throw new UnsupportedOperationException(); } + @Override + protected boolean mustReduceOnSingleInternalAgg() { + return true; + } + @Override public Object getProperty(List path) { if (this.path.equals(path)) {