Skip to content

Commit 3d6cedf

Browse files
committed
Handle terms query when detecting if a query can match nested docs (#34072)
When nested objects are present in the mappings, we add a filter in queries to exclude them if there is no evidence that the query cannot match in this space. In 6x we visit the query in order to find a mandatory clause that can match root documents only. If we find one we can omit the nested documents filter. Currently only `term` and `range` queries are checked, this change adds the support for `terms` query to effectively remove the nested filter if a mandatory `terms` clause targets a non-nested field. Closes #34067
1 parent c65f2c7 commit 3d6cedf

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

server/src/main/java/org/elasticsearch/index/search/NestedHelper.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.index.search;
2121

22+
import org.apache.lucene.index.PrefixCodedTerms;
2223
import org.apache.lucene.search.BooleanClause;
2324
import org.apache.lucene.search.BooleanQuery;
2425
import org.apache.lucene.search.BoostQuery;
@@ -28,6 +29,7 @@
2829
import org.apache.lucene.search.MatchNoDocsQuery;
2930
import org.apache.lucene.search.PointRangeQuery;
3031
import org.apache.lucene.search.Query;
32+
import org.apache.lucene.search.TermInSetQuery;
3133
import org.apache.lucene.search.TermQuery;
3234
import org.apache.lucene.search.BooleanClause.Occur;
3335
import org.elasticsearch.index.mapper.MapperService;
@@ -54,9 +56,18 @@ public boolean mightMatchNestedDocs(Query query) {
5456
} else if (query instanceof MatchNoDocsQuery) {
5557
return false;
5658
} else if (query instanceof TermQuery) {
57-
// We only handle term queries and range queries, which should already
59+
// We only handle term(s) queries and range queries, which should already
5860
// cover a high majority of use-cases
5961
return mightMatchNestedDocs(((TermQuery) query).getTerm().field());
62+
} else if (query instanceof TermInSetQuery) {
63+
PrefixCodedTerms terms = ((TermInSetQuery) query).getTermData();
64+
if (terms.size() > 0) {
65+
PrefixCodedTerms.TermIterator it = terms.iterator();
66+
it.next();
67+
return mightMatchNestedDocs(it.field());
68+
} else {
69+
return false;
70+
}
6071
} else if (query instanceof PointRangeQuery) {
6172
return mightMatchNestedDocs(((PointRangeQuery) query).getField());
6273
} else if (query instanceof IndexOrDocValuesQuery) {
@@ -118,6 +129,15 @@ public boolean mightMatchNonNestedDocs(Query query, String nestedPath) {
118129
return false;
119130
} else if (query instanceof TermQuery) {
120131
return mightMatchNonNestedDocs(((TermQuery) query).getTerm().field(), nestedPath);
132+
} else if (query instanceof TermInSetQuery) {
133+
PrefixCodedTerms terms = ((TermInSetQuery) query).getTermData();
134+
if (terms.size() > 0) {
135+
PrefixCodedTerms.TermIterator it = terms.iterator();
136+
it.next();
137+
return mightMatchNonNestedDocs(it.field(), nestedPath);
138+
} else {
139+
return false;
140+
}
121141
} else if (query instanceof PointRangeQuery) {
122142
return mightMatchNonNestedDocs(((PointRangeQuery) query).getField(), nestedPath);
123143
} else if (query instanceof IndexOrDocValuesQuery) {

server/src/test/java/org/elasticsearch/index/search/NestedHelperTests.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.elasticsearch.test.ESSingleNodeTestCase;
4141

4242
import java.io.IOException;
43+
import java.util.Collections;
4344

4445
public class NestedHelperTests extends ESSingleNodeTestCase {
4546

@@ -115,6 +116,36 @@ public void testMatchNo() {
115116
assertFalse(new NestedHelper(mapperService).mightMatchNonNestedDocs(new MatchNoDocsQuery(), "nested_missing"));
116117
}
117118

119+
public void testTermsQuery() {
120+
Query termsQuery = mapperService.fullName("foo").termsQuery(Collections.singletonList("bar"), null);
121+
assertFalse(new NestedHelper(mapperService).mightMatchNestedDocs(termsQuery));
122+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested1"));
123+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested2"));
124+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested3"));
125+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested_missing"));
126+
127+
termsQuery = mapperService.fullName("nested1.foo").termsQuery(Collections.singletonList("bar"), null);
128+
assertTrue(new NestedHelper(mapperService).mightMatchNestedDocs(termsQuery));
129+
assertFalse(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested1"));
130+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested2"));
131+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested3"));
132+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested_missing"));
133+
134+
termsQuery = mapperService.fullName("nested2.foo").termsQuery(Collections.singletonList("bar"), null);
135+
assertTrue(new NestedHelper(mapperService).mightMatchNestedDocs(termsQuery));
136+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested1"));
137+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested2"));
138+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested3"));
139+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested_missing"));
140+
141+
termsQuery = mapperService.fullName("nested3.foo").termsQuery(Collections.singletonList("bar"), null);
142+
assertTrue(new NestedHelper(mapperService).mightMatchNestedDocs(termsQuery));
143+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested1"));
144+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested2"));
145+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested3"));
146+
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested_missing"));
147+
}
148+
118149
public void testTermQuery() {
119150
Query termQuery = mapperService.fullName("foo").termQuery("bar", null);
120151
assertFalse(new NestedHelper(mapperService).mightMatchNestedDocs(termQuery));

0 commit comments

Comments
 (0)