Skip to content

Refactor streaming agg query phase planning#20471

Merged
rishabhmaurya merged 19 commits intoopensearch-project:mainfrom
bowenlan-amzn:streaming-agg-planning-refactor
Jan 28, 2026
Merged

Refactor streaming agg query phase planning#20471
rishabhmaurya merged 19 commits intoopensearch-project:mainfrom
bowenlan-amzn:streaming-agg-planning-refactor

Conversation

@bowenlan-amzn
Copy link
Copy Markdown
Member

@bowenlan-amzn bowenlan-amzn commented Jan 23, 2026

Description

Streaming aggregation feature supports an agg defined with

  • Top level should be string terms agg and numeric terms agg
  • Second level/sub aggregation could be numeric terms, cardinality, max, min, sum (we should add avg and value_count soon)
    If multiple aggs fit above constraints, it should also be good.

Segment streaming topN heuristic set to shard_size
Also user has a index level setting to provide the segment topN size.
The final topN is the larger one of these 2

The topN is compared with search.aggregations.streaming.max_estimated_bucket_count to decide whether streaming should be used or not. If exceed, streaming is considered to stream back too many buckets per segment so we will fall back to default aggregation path which send response per shard.

Related Issues

Resolves #[Issue number to be closed when this PR is merged]

Check List

  • Functionality includes testing.
  • API changes companion pull request created, if applicable.
  • Public documentation issue/PR created, if applicable.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 23, 2026

📝 Walkthrough

Walkthrough

This PR refactors the streaming aggregation cost estimation architecture from a runtime collector-tree evaluation model to an early-stage aggregation-factory estimation model, introducing a new StreamingCostEstimable interface while removing the Streamable interface and eliminating the AggregatorTreeEvaluator class that previously managed streaming decisions.

Changes

Cohort / File(s) Summary
Streaming Architecture Refactoring
CHANGELOG.md, server/src/main/java/org/opensearch/search/streaming/Streamable.java, server/src/main/java/org/opensearch/search/streaming/StreamingCostEstimable.java, server/src/main/java/org/opensearch/search/aggregations/AggregatorTreeEvaluator.java, server/src/test/java/org/opensearch/search/aggregations/AggregatorTreeEvaluatorTests.java
Removes Streamable interface and replaces with new StreamingCostEstimable interface; eliminates AggregatorTreeEvaluator that previously evaluated streaming decisions at runtime; shifts cost estimation to factory-level before aggregator creation.
FlushModeResolver Refactoring
server/src/main/java/org/opensearch/search/streaming/FlushModeResolver.java
Major refactoring from collector-tree analysis to aggregation-builder focused approach; replaces resolve(Collector...) with isEligibleForStreaming(AggregatorFactories.Builder) and adds new settings for streaming thresholds; introduces per-aggregation type streaming validation.
StreamingCostMetrics Simplification
server/src/main/java/org/opensearch/search/streaming/StreamingCostMetrics.java, server/src/test/java/org/opensearch/search/streaming/StreamingCostMetricsTests.java, server/src/test/java/org/opensearch/search/streaming/FlushModeResolverTests.java
Reduces record fields from five to two (streamable, topNSize); adds neutral() factory method; updates combination logic to work only with topNSize; refactors tests from integration-style to isolated decision logic.
Terms Aggregator Factory Streaming
server/src/main/java/org/opensearch/search/aggregations/bucket/terms/TermsAggregatorFactory.java
Implements StreamingCostEstimable; adds computeSegTopN() helper; requires FlushMode.PER_SEGMENT explicitly for streaming (previously allowed null); propagates segmentTopN parameter through streaming aggregator creation paths.
Terms Streaming Aggregators
server/src/main/java/org/opensearch/search/aggregations/bucket/terms/StreamNumericTermsAggregator.java, server/src/main/java/org/opensearch/search/aggregations/bucket/terms/StreamStringTermsAggregator.java
Removes Streamable implementation; introduces new segmentTopN parameter; replaces internal segmentSize logic with segmentTopN for top-bucket selection; removes streaming cost metrics methods.
Cardinality Aggregator Streaming
server/src/main/java/org/opensearch/search/aggregations/metrics/CardinalityAggregatorFactory.java, server/src/main/java/org/opensearch/search/aggregations/metrics/StreamCardinalityAggregator.java
Factory now implements StreamingCostEstimable with ordinals-aware estimation; aggregator removes Streamable and adds explicit lifecycle methods (getLeafCollector, doReset, doPostCollection, doClose).
Metric Aggregator Factories (Streamable Removal & StreamingCostEstimable Addition)
server/src/main/java/org/opensearch/search/aggregations/metrics/{AvgAggregatorFactory,MaxAggregatorFactory,MinAggregatorFactory,SumAggregatorFactory,ValueCountAggregatorFactory}.java
Each now implements StreamingCostEstimable returning neutral cost metrics; removes responsibility for runtime streaming cost estimation.
Metric Aggregators (Streamable Removal)
server/src/main/java/org/opensearch/search/aggregations/metrics/{MaxAggregator,MinAggregator}.java
Removes Streamable interface implementation and getStreamingCostMetrics() method from both classes.
Aggregator Factories & Collection Management
server/src/main/java/org/opensearch/search/aggregations/AggregatorFactories.java, server/src/main/java/org/opensearch/search/aggregations/AggregationCollectorManager.java
AggregatorFactories adds streaming cost estimation workflow for top-level aggregators using new factory-level cost analysis; AggregationCollectorManager removes dynamic evaluation/recreation step in createCollector.
Profiling & Search Integration
server/src/main/java/org/opensearch/search/profile/aggregation/ProfilingAggregator.java, server/src/main/java/org/opensearch/rest/action/search/RestSearchAction.java
Removes Streamable implementation from ProfilingAggregator; simplifies canUseStreamSearch to delegate to FlushModeResolver.isEligibleForStreaming() instead of checking specific aggregation types.
Test Coverage Updates
server/src/test/java/org/opensearch/rest/action/search/RestSearchActionTests.java, server/src/test/java/org/opensearch/search/aggregations/FactoryStreamingCostEstimationTests.java, server/src/test/java/org/opensearch/search/aggregations/bucket/terms/StreamNumericTermsAggregatorTests.java, server/src/test/java/org/opensearch/search/aggregations/bucket/terms/StreamStringTermsAggregatorTests.java, server/src/test/java/org/opensearch/search/aggregations/metrics/{MaxAggregatorTests,MinAggregatorTests,StreamCardinalityAggregatorTests}.java
Removes old streaming cost metrics tests; adds comprehensive new factory-level streaming cost estimation tests; updates integration tests to use profile-based validation instead of assertions on Streamable interface.
Integration Tests & Test Framework
plugins/arrow-flight-rpc/src/internalClusterTest/java/org/opensearch/streaming/aggregation/SubAggregationIT.java, test/framework/src/main/java/org/opensearch/search/aggregations/AggregatorTestCase.java
Integration tests refactored to use profile inspection for streaming validation with dynamic settings adjustments; test framework explicitly sets FlushMode.PER_SEGMENT in streaming aggregator creation paths.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

enhancement, Search, Search:Aggregations, Search:Performance

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.12% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Refactor streaming agg query phase planning' directly and concisely describes the main change—a refactoring of streaming aggregation query phase planning logic.
Description check ✅ Passed The pull request description includes all required sections: a clear description of the feature (streaming aggregation constraints), related issues placeholder, and a completed checklist with testing and documentation confirmations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for bb004fb: ABORTED

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@bowenlan-amzn bowenlan-amzn force-pushed the streaming-agg-planning-refactor branch from bb004fb to 012735b Compare January 24, 2026 18:03
@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for 012735b: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@bowenlan-amzn bowenlan-amzn force-pushed the streaming-agg-planning-refactor branch from 012735b to 13f2252 Compare January 24, 2026 19:35
@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for 13f2252: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
@bowenlan-amzn bowenlan-amzn force-pushed the streaming-agg-planning-refactor branch from 13f2252 to ddf0f03 Compare January 27, 2026 19:05
@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for 889a7c0: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
@bowenlan-amzn bowenlan-amzn force-pushed the streaming-agg-planning-refactor branch from 889a7c0 to e03943d Compare January 27, 2026 23:17
…stant across segments, not per aggregator

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for b217ab9: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

…ator

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for 6d8c16c: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

- segmentTopN for term agg

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
- rest layer filter streaming

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for 597b0cc: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
@bowenlan-amzn bowenlan-amzn marked this pull request as ready for review January 28, 2026 16:12
Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for 213a6ab: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for ab931dd: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
@bowenlan-amzn bowenlan-amzn force-pushed the streaming-agg-planning-refactor branch from 60c253d to 6ddb9e1 Compare January 28, 2026 18:25
Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for dbe69b6: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

✅ Gradle check result for 99a50a5: SUCCESS

@codecov
Copy link
Copy Markdown

codecov bot commented Jan 28, 2026

Codecov Report

❌ Patch coverage is 77.58621% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.35%. Comparing base (fc33a53) to head (99a50a5).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
...nsearch/search/streaming/StreamingCostMetrics.java 55.17% 3 Missing and 10 partials ⚠️
...regations/bucket/terms/TermsAggregatorFactory.java 80.95% 1 Missing and 3 partials ⚠️
...earch/search/aggregations/AggregatorFactories.java 75.00% 1 Missing and 2 partials ⚠️
...egations/metrics/CardinalityAggregatorFactory.java 66.66% 1 Missing and 1 partial ⚠️
...rch/search/aggregations/metrics/SumAggregator.java 60.00% 0 Missing and 2 partials ⚠️
.../main/java/org/opensearch/index/IndexSettings.java 75.00% 1 Missing ⚠️
...opensearch/search/streaming/FlushModeResolver.java 96.29% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main   #20471      +/-   ##
============================================
+ Coverage     73.19%   73.35%   +0.15%     
- Complexity    71975    72112     +137     
============================================
  Files          5796     5795       -1     
  Lines        329539   329462      -77     
  Branches      47465    47458       -7     
============================================
+ Hits         241220   241675     +455     
+ Misses        69005    68452     -553     
- Partials      19314    19335      +21     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@rishabhmaurya rishabhmaurya merged commit 0d58b07 into opensearch-project:main Jan 28, 2026
37 checks passed
@bowenlan-amzn bowenlan-amzn added the v3.5.0 Issues and PRs related to version 3.5.0 label Jan 28, 2026
tanyabti pushed a commit to tanyabti/OpenSearch that referenced this pull request Feb 24, 2026
* Refactor streaming agg query phase planning

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* Refactor null out from estimation recursive loop

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* Refactor out the segment size from streaming cost metric, as it's constant across segments, not per aggregator

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* Consolidate duplicate ordinals estimation logic in StreamingCostEstimator

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* - only depend on topN to decide streaming
- segmentTopN for term agg

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* - refactor metrics to only provide topN
- rest layer filter streaming

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* fix card IT

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* segmentTopN

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* add change log

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* add test

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* refactor

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* refactor segment size setting

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* remove not supported metric, avg, valuecount, looking into sum for now, if not supported, will remove

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* support sum with integration test

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* fix test

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* refactor sub agg it

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* only allow 2 terms nested, not more

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* address comment, comment out flaky test

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

---------

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
tanyabti pushed a commit to tanyabti/OpenSearch that referenced this pull request Feb 24, 2026
* Refactor streaming agg query phase planning

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* Refactor null out from estimation recursive loop

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* Refactor out the segment size from streaming cost metric, as it's constant across segments, not per aggregator

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* Consolidate duplicate ordinals estimation logic in StreamingCostEstimator

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* - only depend on topN to decide streaming
- segmentTopN for term agg

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* - refactor metrics to only provide topN
- rest layer filter streaming

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* fix card IT

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* segmentTopN

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* add change log

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* add test

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* refactor

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* refactor segment size setting

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* remove not supported metric, avg, valuecount, looking into sum for now, if not supported, will remove

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* support sum with integration test

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* fix test

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* refactor sub agg it

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* only allow 2 terms nested, not more

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

* address comment, comment out flaky test

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>

---------

Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v3.5.0 Issues and PRs related to version 3.5.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants