Skip to content

Commit 1ebf7a1

Browse files
committed
Update per comments
Signed-off-by: Atri Sharma <atri.jiit@gmail.com>
1 parent 89c8998 commit 1ebf7a1

File tree

5 files changed

+50
-58
lines changed

5 files changed

+50
-58
lines changed

server/src/main/java/org/opensearch/search/SearchService.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,10 @@ public SearchService(
529529
this.concurrentSearchDeciderFactories = concurrentSearchDeciderFactories;
530530

531531
this.pluginProfilers = pluginProfilers;
532+
533+
// Initialize QueryRewriterRegistry with cluster settings so TermsMergingRewriter
534+
// can register its settings update consumer
535+
QueryRewriterRegistry.initialize(settings, clusterService.getClusterSettings());
532536
}
533537

534538
private void validateKeepAlives(TimeValue defaultKeepAlive, TimeValue maxKeepAlive) {
@@ -1514,8 +1518,7 @@ private void parseSource(DefaultSearchContext context, SearchSourceBuilder sourc
15141518

15151519
// Apply query rewriting optimizations if enabled
15161520
if (QUERY_REWRITING_ENABLED_SETTING.get(clusterService.getSettings())) {
1517-
int termsThreshold = QUERY_REWRITING_TERMS_THRESHOLD_SETTING.get(clusterService.getSettings());
1518-
query = QueryRewriterRegistry.rewrite(query, queryShardContext, true, termsThreshold);
1521+
query = QueryRewriterRegistry.rewrite(query, queryShardContext, true);
15191522
}
15201523

15211524
InnerHitContextBuilder.extractInnerHits(query, innerHitBuilders);

server/src/main/java/org/opensearch/search/query/QueryRewriterRegistry.java

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
import org.apache.logging.log4j.LogManager;
1212
import org.apache.logging.log4j.Logger;
13+
import org.opensearch.common.settings.ClusterSettings;
14+
import org.opensearch.common.settings.Settings;
1315
import org.opensearch.index.query.QueryBuilder;
1416
import org.opensearch.index.query.QueryShardContext;
1517
import org.opensearch.search.query.rewriters.BooleanFlatteningRewriter;
@@ -40,15 +42,23 @@ public final class QueryRewriterRegistry {
4042
*/
4143
private final CopyOnWriteArrayList<QueryRewriter> rewriters;
4244

45+
/**
46+
* TermsMergingRewriter instance that needs settings initialization.
47+
*/
48+
private final TermsMergingRewriter termsMergingRewriter;
49+
4350
private QueryRewriterRegistry() {
4451
this.rewriters = new CopyOnWriteArrayList<>();
4552

4653
// Register default rewriters
47-
// Note: TermsMergingRewriter is special - it needs threshold at runtime
4854
registerRewriter(new BooleanFlatteningRewriter());
4955
registerRewriter(new MustToFilterRewriter());
5056
registerRewriter(new MustNotToShouldRewriter());
5157
registerRewriter(new MatchAllRemovalRewriter());
58+
59+
// TermsMergingRewriter is registered as singleton
60+
this.termsMergingRewriter = new TermsMergingRewriter();
61+
registerRewriter(termsMergingRewriter);
5262
}
5363

5464
/**
@@ -71,28 +81,25 @@ public void registerRewriter(QueryRewriter rewriter) {
7181
}
7282

7383
/**
74-
* Get a list of all rewriters with the given terms threshold.
84+
* Initialize the registry with cluster settings.
85+
* This must be called once during system startup to properly configure
86+
* the TermsMergingRewriter with settings and update consumers.
87+
*
88+
* @param settings Initial cluster settings
89+
* @param clusterSettings Cluster settings for registering update consumers
7590
*/
76-
private List<QueryRewriter> getRewritersWithThreshold(int termsThreshold) {
77-
List<QueryRewriter> allRewriters = new ArrayList<>(rewriters);
78-
// Add TermsMergingRewriter with the current threshold
79-
// This is added dynamically because it needs the threshold parameter
80-
allRewriters.add(new TermsMergingRewriter(termsThreshold));
81-
allRewriters.sort(Comparator.comparingInt(QueryRewriter::priority));
82-
return allRewriters;
91+
public static void initialize(Settings settings, ClusterSettings clusterSettings) {
92+
getInstance().termsMergingRewriter.initialize(settings, clusterSettings);
8393
}
8494

8595
public static QueryBuilder rewrite(QueryBuilder query, QueryShardContext context, boolean enabled) {
86-
return rewrite(query, context, enabled, 16);
87-
}
88-
89-
public static QueryBuilder rewrite(QueryBuilder query, QueryShardContext context, boolean enabled, int termsThreshold) {
9096
if (!enabled || query == null) {
9197
return query;
9298
}
9399

94100
QueryRewriterRegistry registry = getInstance();
95-
List<QueryRewriter> sortedRewriters = registry.getRewritersWithThreshold(termsThreshold);
101+
List<QueryRewriter> sortedRewriters = new ArrayList<>(registry.rewriters);
102+
sortedRewriters.sort(Comparator.comparingInt(QueryRewriter::priority));
96103

97104
QueryBuilder current = query;
98105
for (QueryRewriter rewriter : sortedRewriters) {

server/src/main/java/org/opensearch/search/query/rewriters/MatchAllRemovalRewriter.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
package org.opensearch.search.query.rewriters;
1010

1111
import org.opensearch.index.query.BoolQueryBuilder;
12-
import org.opensearch.index.query.ConstantScoreQueryBuilder;
1312
import org.opensearch.index.query.MatchAllQueryBuilder;
1413
import org.opensearch.index.query.QueryBuilder;
1514
import org.opensearch.index.query.QueryShardContext;
@@ -43,11 +42,8 @@ private QueryBuilder rewriteBoolQuery(BoolQueryBuilder original) {
4342
if (q instanceof MatchAllQueryBuilder) {
4443
matchAllCount++;
4544
matchAllInMust++;
46-
} else if (q instanceof ConstantScoreQueryBuilder) {
47-
// Don't treat constant score queries as match_all even if they contain match_all
48-
onlyMatchAll = false;
49-
break;
5045
} else {
46+
// Don't treat constant score queries or any other queries as match_all
5147
onlyMatchAll = false;
5248
break;
5349
}
@@ -83,15 +79,18 @@ private QueryBuilder rewriteBoolQuery(BoolQueryBuilder original) {
8379
return original;
8480
}
8581

86-
// Create rewritten query
82+
// Clone the query structure
8783
BoolQueryBuilder rewritten = new BoolQueryBuilder();
8884
rewritten.boost(original.boost());
8985
rewritten.queryName(original.queryName());
9086
rewritten.minimumShouldMatch(original.minimumShouldMatch());
9187
rewritten.adjustPureNegative(original.adjustPureNegative());
9288

93-
// Process all clauses
94-
// For must clauses, only remove match_all if there are other non-match_all queries
89+
// Process each clause type with different match_all removal logic:
90+
// - must: Remove match_all only if other queries exist (preserves scoring semantics)
91+
// - filter: Always remove match_all (it's redundant in non-scoring context)
92+
// - should: Keep match_all (changes OR semantics if removed)
93+
// - mustNot: Keep match_all (excluding all docs is meaningful)
9594
processClausesWithContext(original.must(), rewritten::must, true, original, true);
9695
processClauses(original.filter(), rewritten::filter, true, original);
9796
processClauses(original.should(), rewritten::should, false, original);

server/src/main/java/org/opensearch/search/query/rewriters/TermsMergingRewriter.java

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@
88

99
package org.opensearch.search.query.rewriters;
1010

11+
import org.opensearch.common.settings.ClusterSettings;
12+
import org.opensearch.common.settings.Settings;
1113
import org.opensearch.index.query.BoolQueryBuilder;
1214
import org.opensearch.index.query.QueryBuilder;
1315
import org.opensearch.index.query.QueryShardContext;
1416
import org.opensearch.index.query.TermQueryBuilder;
1517
import org.opensearch.index.query.TermsQueryBuilder;
18+
import org.opensearch.search.SearchService;
1619
import org.opensearch.search.query.QueryRewriter;
1720

1821
import java.util.ArrayList;
@@ -55,24 +58,28 @@ public class TermsMergingRewriter implements QueryRewriter {
5558
private static final int DEFAULT_MINIMUM_TERMS_TO_MERGE = 16;
5659

5760
/**
58-
* The minimum number of terms to merge for this instance.
61+
* The minimum number of terms to merge.
5962
*/
60-
private final int minimumTermsToMerge;
63+
private volatile int minimumTermsToMerge = DEFAULT_MINIMUM_TERMS_TO_MERGE;
6164

6265
/**
63-
* Creates a new rewriter with the default threshold.
66+
* Creates a new rewriter.
6467
*/
65-
public TermsMergingRewriter() {
66-
this(DEFAULT_MINIMUM_TERMS_TO_MERGE);
67-
}
68+
public TermsMergingRewriter() {}
6869

6970
/**
70-
* Creates a new rewriter with a custom threshold.
71+
* Initialize this rewriter with cluster settings.
72+
* This registers an update consumer to keep the threshold in sync with the cluster setting.
7173
*
72-
* @param minimumTermsToMerge The minimum number of terms to merge
74+
* @param settings Initial settings
75+
* @param clusterSettings Cluster settings to register update consumer
7376
*/
74-
public TermsMergingRewriter(int minimumTermsToMerge) {
75-
this.minimumTermsToMerge = minimumTermsToMerge;
77+
public void initialize(Settings settings, ClusterSettings clusterSettings) {
78+
this.minimumTermsToMerge = SearchService.QUERY_REWRITING_TERMS_THRESHOLD_SETTING.get(settings);
79+
clusterSettings.addSettingsUpdateConsumer(
80+
SearchService.QUERY_REWRITING_TERMS_THRESHOLD_SETTING,
81+
threshold -> this.minimumTermsToMerge = threshold
82+
);
7683
}
7784

7885
@Override

server/src/test/java/org/opensearch/search/query/rewriters/TermsMergingRewriterTests.java

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
public class TermsMergingRewriterTests extends OpenSearchTestCase {
2323

2424
private final TermsMergingRewriter rewriter = new TermsMergingRewriter();
25-
private final TermsMergingRewriter customThresholdRewriter = new TermsMergingRewriter(5);
2625
private final QueryShardContext context = mock(QueryShardContext.class);
2726

2827
public void testSimpleTermMergingBelowThreshold() {
@@ -290,27 +289,4 @@ public void testMixedTermsAndTermQueriesAboveThreshold() {
290289
assertThat(merged.values().size(), equalTo(20));
291290
}
292291

293-
public void testCustomThreshold() {
294-
// Test with custom threshold of 5
295-
BoolQueryBuilder query = QueryBuilders.boolQuery();
296-
297-
// Add 6 term queries (above custom threshold of 5)
298-
for (int i = 0; i < 6; i++) {
299-
query.filter(QueryBuilders.termQuery("field", "value" + i));
300-
}
301-
302-
// Should merge with custom threshold rewriter
303-
QueryBuilder rewritten = customThresholdRewriter.rewrite(query, context);
304-
assertThat(rewritten, instanceOf(BoolQueryBuilder.class));
305-
BoolQueryBuilder rewrittenBool = (BoolQueryBuilder) rewritten;
306-
307-
assertThat(rewrittenBool.filter().size(), equalTo(1));
308-
assertThat(rewrittenBool.filter().get(0), instanceOf(TermsQueryBuilder.class));
309-
TermsQueryBuilder termsQuery = (TermsQueryBuilder) rewrittenBool.filter().get(0);
310-
assertThat(termsQuery.values().size(), equalTo(6));
311-
312-
// Should NOT merge with default threshold rewriter (6 < 16)
313-
QueryBuilder defaultRewritten = rewriter.rewrite(query, context);
314-
assertSame(query, defaultRewritten); // No changes expected
315-
}
316292
}

0 commit comments

Comments
 (0)