diff --git a/CHANGELOG-3.0.md b/CHANGELOG-3.0.md index 48d978bede420..4319b31cb8766 100644 --- a/CHANGELOG-3.0.md +++ b/CHANGELOG-3.0.md @@ -49,6 +49,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Fix 'org.apache.hc.core5.http.ParseException: Invalid protocol version' under JDK 16+ ([#4827](https://github.com/opensearch-project/OpenSearch/pull/4827)) - Fix compression support for h2c protocol ([#4944](https://github.com/opensearch-project/OpenSearch/pull/4944)) - Don't over-allocate in HeapBufferedAsyncEntityConsumer in order to consume the response ([#9993](https://github.com/opensearch-project/OpenSearch/pull/9993)) +- Add empty query collector context constant with TOP_SCORES score mode ([#16660](https://github.com/opensearch-project/OpenSearch/pull/16660)) ### Security diff --git a/server/src/main/java/org/opensearch/search/query/QueryCollectorContext.java b/server/src/main/java/org/opensearch/search/query/QueryCollectorContext.java index 08b048cf682bb..32087af75288d 100644 --- a/server/src/main/java/org/opensearch/search/query/QueryCollectorContext.java +++ b/server/src/main/java/org/opensearch/search/query/QueryCollectorContext.java @@ -54,6 +54,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Locale; import static org.opensearch.search.profile.query.CollectorResult.REASON_SEARCH_MIN_SCORE; import static org.opensearch.search.profile.query.CollectorResult.REASON_SEARCH_MULTI; @@ -67,38 +68,52 @@ */ @PublicApi(since = "1.0.0") public abstract class QueryCollectorContext { - private static final Collector EMPTY_COLLECTOR = new SimpleCollector() { - @Override - public void collect(int doc) {} - @Override - public ScoreMode scoreMode() { - return ScoreMode.COMPLETE_NO_SCORES; - } - }; + private static Collector createEmptyCollector(ScoreMode scoreMode) { + return new SimpleCollector() { + @Override + public void collect(int doc) {} - public static final QueryCollectorContext EMPTY_CONTEXT = new QueryCollectorContext("empty") { + @Override + public ScoreMode scoreMode() { + return scoreMode; + } + }; + } - @Override - Collector create(Collector in) throws IOException { - return EMPTY_COLLECTOR; - } + private static final ReduceableSearchResult EMPTY_RESULT = result -> {}; - @Override - CollectorManager createManager(CollectorManager in) throws IOException { - return new CollectorManager() { - @Override - public Collector newCollector() throws IOException { - return EMPTY_COLLECTOR; - } + private static QueryCollectorContext createEmptyContext(Collector collector) { + String name = String.format(Locale.ROOT, "empty_with_score_mode_%s", collector.scoreMode().toString().toLowerCase(Locale.ROOT)); + return new QueryCollectorContext(name) { + @Override + Collector create(Collector in) { + return collector; + } - @Override - public ReduceableSearchResult reduce(Collection collectors) throws IOException { - return result -> {}; - } - }; - } - }; + @Override + CollectorManager createManager(CollectorManager in) { + return new CollectorManager<>() { + @Override + public Collector newCollector() { + return collector; + } + + @Override + public ReduceableSearchResult reduce(Collection collectors) { + return EMPTY_RESULT; + } + }; + + } + }; + } + + private static final Collector EMPTY_COLLECTOR = createEmptyCollector(ScoreMode.COMPLETE_NO_SCORES); + private static final Collector EMPTY_COLLECTOR_TOP_SCORES = createEmptyCollector(ScoreMode.TOP_SCORES); + + public static final QueryCollectorContext EMPTY_CONTEXT = createEmptyContext(EMPTY_COLLECTOR); + public static final QueryCollectorContext EMPTY_CONTEXT_TOP_SCORES_SCORE_MODE = createEmptyContext(EMPTY_COLLECTOR_TOP_SCORES); private String profilerName; diff --git a/server/src/test/java/org/opensearch/search/query/QueryPhaseTests.java b/server/src/test/java/org/opensearch/search/query/QueryPhaseTests.java index 84057ab1a1b15..846e7b9675dec 100644 --- a/server/src/test/java/org/opensearch/search/query/QueryPhaseTests.java +++ b/server/src/test/java/org/opensearch/search/query/QueryPhaseTests.java @@ -1197,6 +1197,16 @@ private void createTimeoutCheckerThenWaitThenRun( verifyNoMoreInteractions(mockedSearchContext); } + public void testEmptyQueryCollectorContextAndDifferentScoreModes() throws Exception { + QueryCollectorContext topScoresContext = QueryCollectorContext.EMPTY_CONTEXT_TOP_SCORES_SCORE_MODE; + + // Verify score mode + assertEquals(org.apache.lucene.search.ScoreMode.TOP_SCORES, topScoresContext.create(null).scoreMode()); + + // Verify it's a different instance than empty context + assertNotEquals(QueryCollectorContext.EMPTY_CONTEXT, topScoresContext); + } + private static class TestSearchContextWithRewriteAndCancellation extends TestSearchContext { private TestSearchContextWithRewriteAndCancellation(