From 27b53b8edfac1844a33389af9e97bc062f8b69dc Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Mon, 23 Dec 2013 13:53:20 +0100 Subject: [PATCH] Fixed named filter and query support for the top_children, has_child and has_parent queries and filters. Closes #4534 --- .../index/query/HasChildFilterParser.java | 2 +- .../index/query/HasChildQueryParser.java | 7 +-- .../index/query/HasParentFilterParser.java | 2 +- .../index/query/HasParentQueryParser.java | 3 +- .../index/query/TopChildrenQueryParser.java | 17 +++---- .../child/SimpleChildQuerySearchTests.java | 48 +++++++++++++++++++ 6 files changed, 63 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/elasticsearch/index/query/HasChildFilterParser.java b/src/main/java/org/elasticsearch/index/query/HasChildFilterParser.java index 766128f8055..0e9cbb92f37 100644 --- a/src/main/java/org/elasticsearch/index/query/HasChildFilterParser.java +++ b/src/main/java/org/elasticsearch/index/query/HasChildFilterParser.java @@ -144,7 +144,7 @@ public class HasChildFilterParser implements FilterParser { Query childrenConstantScoreQuery = new ChildrenConstantScoreQuery(query, parentType, childType, parentFilter, shortCircuitParentDocSet, nonNestedDocsFilter); if (filterName != null) { - parseContext.addNamedQuery(filterName, childrenConstantScoreQuery); + parseContext.addNamedFilter(filterName, new CustomQueryWrappingFilter(childrenConstantScoreQuery)); } boolean deleteByQuery = "delete_by_query".equals(SearchContext.current().source()); diff --git a/src/main/java/org/elasticsearch/index/query/HasChildQueryParser.java b/src/main/java/org/elasticsearch/index/query/HasChildQueryParser.java index 34194067af9..a0db190be01 100644 --- a/src/main/java/org/elasticsearch/index/query/HasChildQueryParser.java +++ b/src/main/java/org/elasticsearch/index/query/HasChildQueryParser.java @@ -27,10 +27,7 @@ import org.elasticsearch.common.lucene.search.XConstantScoreQuery; import org.elasticsearch.common.lucene.search.XFilteredQuery; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.mapper.DocumentMapper; -import org.elasticsearch.index.search.child.ChildrenConstantScoreQuery; -import org.elasticsearch.index.search.child.ChildrenQuery; -import org.elasticsearch.index.search.child.DeleteByQueryWrappingFilter; -import org.elasticsearch.index.search.child.ScoreType; +import org.elasticsearch.index.search.child.*; import org.elasticsearch.index.search.nested.NonNestedDocsFilter; import org.elasticsearch.search.internal.SearchContext; @@ -154,7 +151,7 @@ public class HasChildQueryParser implements QueryParser { } } if (queryName != null) { - parseContext.addNamedQuery(queryName, query); + parseContext.addNamedFilter(queryName, new CustomQueryWrappingFilter(query)); } query.setBoost(boost); return query; diff --git a/src/main/java/org/elasticsearch/index/query/HasParentFilterParser.java b/src/main/java/org/elasticsearch/index/query/HasParentFilterParser.java index 841a075aece..5d898ca84bd 100644 --- a/src/main/java/org/elasticsearch/index/query/HasParentFilterParser.java +++ b/src/main/java/org/elasticsearch/index/query/HasParentFilterParser.java @@ -161,7 +161,7 @@ public class HasParentFilterParser implements FilterParser { Query parentConstantScoreQuery = new ParentConstantScoreQuery(query, parentType, childrenFilter); if (filterName != null) { - parseContext.addNamedQuery(filterName, parentConstantScoreQuery); + parseContext.addNamedFilter(filterName, new CustomQueryWrappingFilter(parentConstantScoreQuery)); } boolean deleteByQuery = "delete_by_query".equals(SearchContext.current().source()); diff --git a/src/main/java/org/elasticsearch/index/query/HasParentQueryParser.java b/src/main/java/org/elasticsearch/index/query/HasParentQueryParser.java index dcc995d0148..b6548aefd33 100644 --- a/src/main/java/org/elasticsearch/index/query/HasParentQueryParser.java +++ b/src/main/java/org/elasticsearch/index/query/HasParentQueryParser.java @@ -31,6 +31,7 @@ import org.elasticsearch.common.lucene.search.XFilteredQuery; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.internal.ParentFieldMapper; +import org.elasticsearch.index.search.child.CustomQueryWrappingFilter; import org.elasticsearch.index.search.child.DeleteByQueryWrappingFilter; import org.elasticsearch.index.search.child.ParentConstantScoreQuery; import org.elasticsearch.index.search.child.ParentQuery; @@ -170,7 +171,7 @@ public class HasParentQueryParser implements QueryParser { } query.setBoost(boost); if (queryName != null) { - parseContext.addNamedQuery(queryName, query); + parseContext.addNamedFilter(queryName, new CustomQueryWrappingFilter(query)); } return query; } diff --git a/src/main/java/org/elasticsearch/index/query/TopChildrenQueryParser.java b/src/main/java/org/elasticsearch/index/query/TopChildrenQueryParser.java index eccb2f81459..484518d6b9b 100644 --- a/src/main/java/org/elasticsearch/index/query/TopChildrenQueryParser.java +++ b/src/main/java/org/elasticsearch/index/query/TopChildrenQueryParser.java @@ -25,6 +25,7 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.lucene.search.XFilteredQuery; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.mapper.DocumentMapper; +import org.elasticsearch.index.search.child.CustomQueryWrappingFilter; import org.elasticsearch.index.search.child.ScoreType; import org.elasticsearch.index.search.child.TopChildrenQuery; import org.elasticsearch.search.internal.SearchContext; @@ -51,7 +52,7 @@ public class TopChildrenQueryParser implements QueryParser { public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); - Query query = null; + Query innerQuery = null; boolean queryFound = false; float boost = 1.0f; String childType = null; @@ -72,7 +73,7 @@ public class TopChildrenQueryParser implements QueryParser { // since we switch types, make sure we change the context String[] origTypes = QueryParseContext.setTypesWithPrevious(childType == null ? null : new String[]{childType}); try { - query = parseContext.parseInnerQuery(); + innerQuery = parseContext.parseInnerQuery(); } finally { QueryParseContext.setTypes(origTypes); } @@ -108,7 +109,7 @@ public class TopChildrenQueryParser implements QueryParser { throw new QueryParsingException(parseContext.index(), "[top_children] requires 'type' field"); } - if (query == null) { + if (innerQuery == null) { return null; } @@ -125,13 +126,13 @@ public class TopChildrenQueryParser implements QueryParser { } String parentType = childDocMapper.parentFieldMapper().type(); - query.setBoost(boost); + innerQuery.setBoost(boost); // wrap the query with type query - query = new XFilteredQuery(query, parseContext.cacheFilter(childDocMapper.typeFilter(), null)); - TopChildrenQuery childQuery = new TopChildrenQuery(query, childType, parentType, scoreType, factor, incrementalFactor, parseContext.cacheRecycler()); + innerQuery = new XFilteredQuery(innerQuery, parseContext.cacheFilter(childDocMapper.typeFilter(), null)); + TopChildrenQuery query = new TopChildrenQuery(innerQuery, childType, parentType, scoreType, factor, incrementalFactor, parseContext.cacheRecycler()); if (queryName != null) { - parseContext.addNamedQuery(queryName, childQuery); + parseContext.addNamedFilter(queryName, new CustomQueryWrappingFilter(query)); } - return childQuery; + return query; } } diff --git a/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java b/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java index 574137c0a16..469bf5aef45 100644 --- a/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java +++ b/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java @@ -2004,6 +2004,54 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest { assertThat(searchResponse.getHits().totalHits(), equalTo(2l)); } + @Test + public void testNamedFilters() throws Exception { + client().admin().indices().prepareCreate("test") + .setSettings(ImmutableSettings.settingsBuilder().put("index.number_of_shards", 1).put("index.number_of_replicas", 0)) + .execute().actionGet(); + client().admin().cluster().prepareHealth().setWaitForEvents(Priority.LANGUID).setWaitForGreenStatus().execute().actionGet(); + client().admin() + .indices() + .preparePutMapping("test") + .setType("child") + .setSource("_parent", "type=parent").execute().actionGet(); + + String parentId = "p1"; + client().prepareIndex("test", "parent", parentId).setSource("p_field", "1").execute().actionGet(); + client().prepareIndex("test", "child", "c1").setSource("c_field", "1").setParent(parentId).execute().actionGet(); + client().admin().indices().prepareRefresh().execute().actionGet(); + + SearchResponse searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "1")).queryName("test")) + .execute().actionGet(); + assertHitCount(searchResponse, 1l); + assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test")); + + searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", termQuery("c_field", "1")).scoreType("max").queryName("test")) + .execute().actionGet(); + assertHitCount(searchResponse, 1l); + assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test")); + + searchResponse = client().prepareSearch("test").setQuery(hasParentQuery("parent", termQuery("p_field", "1")).scoreType("score").queryName("test")) + .execute().actionGet(); + assertHitCount(searchResponse, 1l); + assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test")); + + searchResponse = client().prepareSearch("test").setQuery(constantScoreQuery(hasChildFilter("child", termQuery("c_field", "1")).filterName("test"))) + .execute().actionGet(); + assertHitCount(searchResponse, 1l); + assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test")); + + searchResponse = client().prepareSearch("test").setQuery(constantScoreQuery(hasParentFilter("parent", termQuery("p_field", "1")).filterName("test"))) + .execute().actionGet(); + assertHitCount(searchResponse, 1l); + assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1)); + assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test")); + } + private static HasChildFilterBuilder hasChildFilter(String type, QueryBuilder queryBuilder) { HasChildFilterBuilder hasChildFilterBuilder = FilterBuilders.hasChildFilter(type, queryBuilder); hasChildFilterBuilder.setShortCircuitCutoff(randomInt(10));