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
This commit is contained in:
parent
2aff005a69
commit
aba4a59d0d
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.index.search;
|
||||
|
||||
import org.apache.lucene.index.PrefixCodedTerms;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.BoostQuery;
|
||||
|
@ -28,6 +29,7 @@ import org.apache.lucene.search.MatchAllDocsQuery;
|
|||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.PointRangeQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermInSetQuery;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.apache.lucene.search.BooleanClause.Occur;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
|
@ -54,9 +56,18 @@ public final class NestedHelper {
|
|||
} else if (query instanceof MatchNoDocsQuery) {
|
||||
return false;
|
||||
} else if (query instanceof TermQuery) {
|
||||
// We only handle term queries and range queries, which should already
|
||||
// We only handle term(s) queries and range queries, which should already
|
||||
// cover a high majority of use-cases
|
||||
return mightMatchNestedDocs(((TermQuery) query).getTerm().field());
|
||||
} else if (query instanceof TermInSetQuery) {
|
||||
PrefixCodedTerms terms = ((TermInSetQuery) query).getTermData();
|
||||
if (terms.size() > 0) {
|
||||
PrefixCodedTerms.TermIterator it = terms.iterator();
|
||||
it.next();
|
||||
return mightMatchNestedDocs(it.field());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (query instanceof PointRangeQuery) {
|
||||
return mightMatchNestedDocs(((PointRangeQuery) query).getField());
|
||||
} else if (query instanceof IndexOrDocValuesQuery) {
|
||||
|
@ -118,6 +129,15 @@ public final class NestedHelper {
|
|||
return false;
|
||||
} else if (query instanceof TermQuery) {
|
||||
return mightMatchNonNestedDocs(((TermQuery) query).getTerm().field(), nestedPath);
|
||||
} else if (query instanceof TermInSetQuery) {
|
||||
PrefixCodedTerms terms = ((TermInSetQuery) query).getTermData();
|
||||
if (terms.size() > 0) {
|
||||
PrefixCodedTerms.TermIterator it = terms.iterator();
|
||||
it.next();
|
||||
return mightMatchNonNestedDocs(it.field(), nestedPath);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (query instanceof PointRangeQuery) {
|
||||
return mightMatchNonNestedDocs(((PointRangeQuery) query).getField(), nestedPath);
|
||||
} else if (query instanceof IndexOrDocValuesQuery) {
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.elasticsearch.index.query.TermQueryBuilder;
|
|||
import org.elasticsearch.test.ESSingleNodeTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
public class NestedHelperTests extends ESSingleNodeTestCase {
|
||||
|
||||
|
@ -115,6 +116,36 @@ public class NestedHelperTests extends ESSingleNodeTestCase {
|
|||
assertFalse(new NestedHelper(mapperService).mightMatchNonNestedDocs(new MatchNoDocsQuery(), "nested_missing"));
|
||||
}
|
||||
|
||||
public void testTermsQuery() {
|
||||
Query termsQuery = mapperService.fullName("foo").termsQuery(Collections.singletonList("bar"), null);
|
||||
assertFalse(new NestedHelper(mapperService).mightMatchNestedDocs(termsQuery));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested1"));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested2"));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested3"));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested_missing"));
|
||||
|
||||
termsQuery = mapperService.fullName("nested1.foo").termsQuery(Collections.singletonList("bar"), null);
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNestedDocs(termsQuery));
|
||||
assertFalse(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested1"));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested2"));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested3"));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested_missing"));
|
||||
|
||||
termsQuery = mapperService.fullName("nested2.foo").termsQuery(Collections.singletonList("bar"), null);
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNestedDocs(termsQuery));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested1"));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested2"));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested3"));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested_missing"));
|
||||
|
||||
termsQuery = mapperService.fullName("nested3.foo").termsQuery(Collections.singletonList("bar"), null);
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNestedDocs(termsQuery));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested1"));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested2"));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested3"));
|
||||
assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termsQuery, "nested_missing"));
|
||||
}
|
||||
|
||||
public void testTermQuery() {
|
||||
Query termQuery = mapperService.fullName("foo").termQuery("bar", null);
|
||||
assertFalse(new NestedHelper(mapperService).mightMatchNestedDocs(termQuery));
|
||||
|
|
Loading…
Reference in New Issue