From efd857e5b8904d3e3a78e4f94c14c200f13f28d7 Mon Sep 17 00:00:00 2001 From: Sandesh Kumar Date: Tue, 29 Jul 2025 13:12:56 -0700 Subject: [PATCH 1/2] add weight.count optimization for no match Signed-off-by: Sandesh Kumar --- .../bucket/composite/CompositeAggregator.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/server/src/main/java/org/opensearch/search/aggregations/bucket/composite/CompositeAggregator.java b/server/src/main/java/org/opensearch/search/aggregations/bucket/composite/CompositeAggregator.java index d08c8121b0535..48a9cb4cc16cd 100644 --- a/server/src/main/java/org/opensearch/search/aggregations/bucket/composite/CompositeAggregator.java +++ b/server/src/main/java/org/opensearch/search/aggregations/bucket/composite/CompositeAggregator.java @@ -119,6 +119,7 @@ public final class CompositeAggregator extends BucketsAggregator { private BucketCollector deferredCollectors; private boolean earlyTerminated; + private Weight weight; private final FilterRewriteOptimizationContext filterRewriteOptimizationContext; private LongKeyedBucketOrds bucketOrds; @@ -567,8 +568,15 @@ private void processLeafFromQuery(LeafReaderContext ctx, Sort indexSortPrefix) t } } + public void setWeight(Weight weight) { + this.weight = weight; + } + @Override protected boolean tryPrecomputeAggregationForLeaf(LeafReaderContext ctx) throws IOException { + if (this.weight != null && this.weight.count(ctx) == 0) { + return true; + } finishLeaf(); // May need to wrap up previous leaf if it could not be precomputed return filterRewriteOptimizationContext.tryOptimize( ctx, From d0b30a3f9d9852da244b0c995723ce7f03126399 Mon Sep 17 00:00:00 2001 From: Sandesh Kumar Date: Tue, 29 Jul 2025 16:25:54 -0700 Subject: [PATCH 2/2] refactor streams to for loop Signed-off-by: Sandesh Kumar --- .../bucket/composite/CompositeAggregator.java | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/server/src/main/java/org/opensearch/search/aggregations/bucket/composite/CompositeAggregator.java b/server/src/main/java/org/opensearch/search/aggregations/bucket/composite/CompositeAggregator.java index 48a9cb4cc16cd..7c57dbb25c653 100644 --- a/server/src/main/java/org/opensearch/search/aggregations/bucket/composite/CompositeAggregator.java +++ b/server/src/main/java/org/opensearch/search/aggregations/bucket/composite/CompositeAggregator.java @@ -91,7 +91,6 @@ import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.LongUnaryOperator; -import java.util.stream.Collectors; import static org.opensearch.search.aggregations.MultiBucketConsumerService.MAX_BUCKET_SETTING; import static org.opensearch.search.aggregations.bucket.filterrewrite.AggregatorBridge.segmentMatchAll; @@ -136,11 +135,31 @@ public final class CompositeAggregator extends BucketsAggregator { ) throws IOException { super(name, factories, context, parent, CardinalityUpperBound.MANY, metadata); this.size = size; - this.sourceNames = Arrays.stream(sourceConfigs).map(CompositeValuesSourceConfig::name).collect(Collectors.toList()); - this.reverseMuls = Arrays.stream(sourceConfigs).mapToInt(CompositeValuesSourceConfig::reverseMul).toArray(); - this.missingOrders = Arrays.stream(sourceConfigs).map(CompositeValuesSourceConfig::missingOrder).toArray(MissingOrder[]::new); - this.formats = Arrays.stream(sourceConfigs).map(CompositeValuesSourceConfig::format).collect(Collectors.toList()); - this.sources = new SingleDimensionValuesSource[sourceConfigs.length]; + final int numSources = sourceConfigs.length; + + // Pre-initialize the destination collections with the correct size + this.sourceNames = new ArrayList<>(numSources); + this.reverseMuls = new int[numSources]; + this.missingOrders = new MissingOrder[numSources]; + this.formats = new ArrayList<>(numSources); + this.sources = new SingleDimensionValuesSource[numSources]; + + // Populate all collections + for (int i = 0; i < numSources; i++) { + CompositeValuesSourceConfig sourceConfig = sourceConfigs[i]; + this.sourceNames.add(sourceConfig.name()); + this.reverseMuls[i] = sourceConfig.reverseMul(); + this.missingOrders[i] = sourceConfig.missingOrder(); + this.formats.add(sourceConfig.format()); + + this.sources[i] = sourceConfig.createValuesSource( + context.bigArrays(), + context.searcher().getIndexReader(), + size, + this::addRequestCircuitBreakerBytes + ); + } + // check that the provided size is not greater than the search.max_buckets setting int bucketLimit = context.aggregations().multiBucketConsumer().getLimit(); if (size > bucketLimit) { @@ -157,14 +176,6 @@ public final class CompositeAggregator extends BucketsAggregator { ); } this.sourceConfigs = sourceConfigs; - for (int i = 0; i < sourceConfigs.length; i++) { - this.sources[i] = sourceConfigs[i].createValuesSource( - context.bigArrays(), - context.searcher().getIndexReader(), - size, - this::addRequestCircuitBreakerBytes - ); - } this.queue = new CompositeValuesCollectorQueue(context.bigArrays(), sources, size, rawAfterKey); this.rawAfterKey = rawAfterKey; @@ -231,7 +242,7 @@ protected int getSize() { @Override protected Function bucketOrdProducer() { - return (key) -> bucketOrds.add(0, getRoundingPrepared().round((long) key)); + return (key) -> bucketOrds.add(0, getRoundingPrepared().round(key)); } }; filterRewriteOptimizationContext = new FilterRewriteOptimizationContext(bridge, parent, subAggregators.length, context);