Browse Source

Avoid adding unnecessary nested filters when ranges are used. (#23427)

The code was testing `PointRangeQuery` however we now use the
`IndexOrDocValuesQuery` in field mappers. This makes the test generate queries
through mappers so that we test the actual queries that would be generated.
Adrien Grand 8 years ago
parent
commit
64c90346c6

+ 5 - 0
core/src/main/java/org/elasticsearch/index/search/NestedHelper.java

@@ -23,6 +23,7 @@ import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.BoostQuery;
 import org.apache.lucene.search.ConstantScoreQuery;
+import org.apache.lucene.search.IndexOrDocValuesQuery;
 import org.apache.lucene.search.MatchAllDocsQuery;
 import org.apache.lucene.search.MatchNoDocsQuery;
 import org.apache.lucene.search.PointRangeQuery;
@@ -58,6 +59,8 @@ public final class NestedHelper {
             return mightMatchNestedDocs(((TermQuery) query).getTerm().field());
         } else if (query instanceof PointRangeQuery) {
             return mightMatchNestedDocs(((PointRangeQuery) query).getField());
+        } else if (query instanceof IndexOrDocValuesQuery) {
+            return mightMatchNestedDocs(((IndexOrDocValuesQuery) query).getIndexQuery());
         } else if (query instanceof BooleanQuery) {
             final BooleanQuery bq = (BooleanQuery) query;
             final boolean hasRequiredClauses = bq.clauses().stream().anyMatch(BooleanClause::isRequired);
@@ -117,6 +120,8 @@ public final class NestedHelper {
             return mightMatchNonNestedDocs(((TermQuery) query).getTerm().field(), nestedPath);
         } else if (query instanceof PointRangeQuery) {
             return mightMatchNonNestedDocs(((PointRangeQuery) query).getField(), nestedPath);
+        } else if (query instanceof IndexOrDocValuesQuery) {
+            return mightMatchNonNestedDocs(((IndexOrDocValuesQuery) query).getIndexQuery(), nestedPath);
         } else if (query instanceof BooleanQuery) {
             final BooleanQuery bq = (BooleanQuery) query;
             final boolean hasRequiredClauses = bq.clauses().stream().anyMatch(BooleanClause::isRequired);

+ 47 - 4
core/src/test/java/org/elasticsearch/index/search/NestedHelperTests.java

@@ -32,6 +32,7 @@ import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 import org.elasticsearch.common.xcontent.XContentFactory;
 import org.elasticsearch.index.IndexService;
+import org.elasticsearch.index.mapper.MappedFieldType;
 import org.elasticsearch.index.mapper.MapperService;
 import org.elasticsearch.index.query.MatchAllQueryBuilder;
 import org.elasticsearch.index.query.NestedQueryBuilder;
@@ -55,12 +56,18 @@ public class NestedHelperTests extends ESSingleNodeTestCase {
                         .startObject("foo")
                             .field("type", "keyword")
                         .endObject()
+                        .startObject("foo2")
+                            .field("type", "long")
+                        .endObject()
                         .startObject("nested1")
                             .field("type", "nested")
                             .startObject("properties")
                                 .startObject("foo")
                                     .field("type", "keyword")
                                 .endObject()
+                                .startObject("foo2")
+                                    .field("type", "long")
+                                .endObject()
                             .endObject()
                         .endObject()
                         .startObject("nested2")
@@ -70,6 +77,9 @@ public class NestedHelperTests extends ESSingleNodeTestCase {
                                 .startObject("foo")
                                     .field("type", "keyword")
                                 .endObject()
+                                .startObject("foo2")
+                                    .field("type", "long")
+                                .endObject()
                             .endObject()
                         .endObject()
                         .startObject("nested3")
@@ -79,6 +89,9 @@ public class NestedHelperTests extends ESSingleNodeTestCase {
                                 .startObject("foo")
                                     .field("type", "keyword")
                                 .endObject()
+                                .startObject("foo2")
+                                    .field("type", "long")
+                                .endObject()
                             .endObject()
                         .endObject()
                     .endObject()
@@ -104,28 +117,28 @@ public class NestedHelperTests extends ESSingleNodeTestCase {
     }
 
     public void testTermQuery() {
-        TermQuery termQuery = new TermQuery(new Term("foo", "bar"));
+        Query termQuery = mapperService.fullName("foo").termQuery("bar", null);
         assertFalse(new NestedHelper(mapperService).mightMatchNestedDocs(termQuery));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested1"));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested2"));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested3"));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested_missing"));
 
-        termQuery = new TermQuery(new Term("nested1.foo", "bar"));
+        termQuery = mapperService.fullName("nested1.foo").termQuery("bar", null);
         assertTrue(new NestedHelper(mapperService).mightMatchNestedDocs(termQuery));
         assertFalse(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested1"));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested2"));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested3"));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested_missing"));
 
-        termQuery = new TermQuery(new Term("nested2.foo", "bar"));
+        termQuery = mapperService.fullName("nested2.foo").termQuery("bar", null);
         assertTrue(new NestedHelper(mapperService).mightMatchNestedDocs(termQuery));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested1"));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested2"));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested3"));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested_missing"));
 
-        termQuery = new TermQuery(new Term("nested3.foo", "bar"));
+        termQuery = mapperService.fullName("nested3.foo").termQuery("bar", null);
         assertTrue(new NestedHelper(mapperService).mightMatchNestedDocs(termQuery));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested1"));
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested2"));
@@ -133,6 +146,36 @@ public class NestedHelperTests extends ESSingleNodeTestCase {
         assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(termQuery, "nested_missing"));
     }
 
+    public void testRangeQuery() {
+        Query rangeQuery = mapperService.fullName("foo2").rangeQuery(2, 5, true, true, null);
+        assertFalse(new NestedHelper(mapperService).mightMatchNestedDocs(rangeQuery));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested1"));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested2"));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested3"));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested_missing"));
+
+        rangeQuery = mapperService.fullName("nested1.foo2").rangeQuery(2, 5, true, true, null);
+        assertTrue(new NestedHelper(mapperService).mightMatchNestedDocs(rangeQuery));
+        assertFalse(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested1"));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested2"));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested3"));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested_missing"));
+
+        rangeQuery = mapperService.fullName("nested2.foo2").rangeQuery(2, 5, true, true, null);
+        assertTrue(new NestedHelper(mapperService).mightMatchNestedDocs(rangeQuery));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested1"));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested2"));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested3"));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested_missing"));
+
+        rangeQuery = mapperService.fullName("nested3.foo2").rangeQuery(2, 5, true, true, null);
+        assertTrue(new NestedHelper(mapperService).mightMatchNestedDocs(rangeQuery));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested1"));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested2"));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested3"));
+        assertTrue(new NestedHelper(mapperService).mightMatchNonNestedDocs(rangeQuery, "nested_missing"));
+    }
+
     public void testDisjunction() {
         BooleanQuery bq = new BooleanQuery.Builder()
                 .add(new TermQuery(new Term("foo", "bar")), Occur.SHOULD)