Fixed `has_parent` query and filter returning no results with multi level child docs.

This commit is contained in:
Martijn van Groningen 2013-06-05 22:12:26 +02:00
parent 56dfa96851
commit 82ff1c6802
3 changed files with 72 additions and 16 deletions

View File

@ -37,8 +37,8 @@ import org.elasticsearch.index.search.child.HasParentFilter;
import org.elasticsearch.search.internal.SearchContext; import org.elasticsearch.search.internal.SearchContext;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.HashSet;
import java.util.List; import java.util.Set;
/** /**
* *
@ -136,17 +136,22 @@ public class HasParentFilterParser implements FilterParser {
throw new ElasticSearchIllegalStateException("[has_parent] Can't execute, search context not set"); throw new ElasticSearchIllegalStateException("[has_parent] Can't execute, search context not set");
} }
List<String> parentTypes = new ArrayList<String>(2); Set<String> parentTypes = new HashSet<String>(5);
parentTypes.add(parentType);
for (DocumentMapper documentMapper : parseContext.mapperService()) { for (DocumentMapper documentMapper : parseContext.mapperService()) {
ParentFieldMapper parentFieldMapper = documentMapper.parentFieldMapper(); ParentFieldMapper parentFieldMapper = documentMapper.parentFieldMapper();
if (parentFieldMapper != null) { if (parentFieldMapper != null) {
parentTypes.add(parentFieldMapper.type()); DocumentMapper parentTypeDocumentMapper = searchContext.mapperService().documentMapper(parentFieldMapper.type());
if (parentTypeDocumentMapper == null) {
// Only add this, if this parentFieldMapper (also a parent) isn't a child of another parent.
parentTypes.add(parentFieldMapper.type());
}
} }
} }
Filter parentFilter; Filter parentFilter;
if (parentTypes.size() == 1) { if (parentTypes.size() == 1) {
DocumentMapper documentMapper = parseContext.mapperService().documentMapper(parentTypes.get(0)); DocumentMapper documentMapper = parseContext.mapperService().documentMapper(parentTypes.iterator().next());
parentFilter = parseContext.cacheFilter(documentMapper.typeFilter(), null); parentFilter = parseContext.cacheFilter(documentMapper.typeFilter(), null);
} else { } else {
XBooleanFilter parentsFilter = new XBooleanFilter(); XBooleanFilter parentsFilter = new XBooleanFilter();

View File

@ -37,8 +37,8 @@ import org.elasticsearch.index.search.child.ParentQuery;
import org.elasticsearch.search.internal.SearchContext; import org.elasticsearch.search.internal.SearchContext;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.HashSet;
import java.util.List; import java.util.Set;
public class HasParentQueryParser implements QueryParser { public class HasParentQueryParser implements QueryParser {
@ -131,17 +131,22 @@ public class HasParentQueryParser implements QueryParser {
throw new ElasticSearchIllegalStateException("[has_parent] Can't execute, search context not set."); throw new ElasticSearchIllegalStateException("[has_parent] Can't execute, search context not set.");
} }
List<String> parentTypes = new ArrayList<String>(2); Set<String> parentTypes = new HashSet<String>(5);
parentTypes.add(parentType);
for (DocumentMapper documentMapper : parseContext.mapperService()) { for (DocumentMapper documentMapper : parseContext.mapperService()) {
ParentFieldMapper parentFieldMapper = documentMapper.parentFieldMapper(); ParentFieldMapper parentFieldMapper = documentMapper.parentFieldMapper();
if (parentFieldMapper != null) { if (parentFieldMapper != null) {
parentTypes.add(parentFieldMapper.type()); DocumentMapper parentTypeDocumentMapper = searchContext.mapperService().documentMapper(parentFieldMapper.type());
if (parentTypeDocumentMapper == null) {
// Only add this, if this parentFieldMapper (also a parent) isn't a child of another parent.
parentTypes.add(parentFieldMapper.type());
}
} }
} }
Filter parentFilter; Filter parentFilter;
if (parentTypes.size() == 1) { if (parentTypes.size() == 1) {
DocumentMapper documentMapper = parseContext.mapperService().documentMapper(parentTypes.get(0)); DocumentMapper documentMapper = parseContext.mapperService().documentMapper(parentTypes.iterator().next());
parentFilter = parseContext.cacheFilter(documentMapper.typeFilter(), null); parentFilter = parseContext.cacheFilter(documentMapper.typeFilter(), null);
} else { } else {
XBooleanFilter parentsFilter = new XBooleanFilter(); XBooleanFilter parentsFilter = new XBooleanFilter();

View File

@ -31,15 +31,10 @@ import org.elasticsearch.search.facet.terms.TermsFacet;
import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.test.integration.AbstractSharedClusterTest; import org.elasticsearch.test.integration.AbstractSharedClusterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static com.google.common.collect.Maps.newHashMap; import static com.google.common.collect.Maps.newHashMap;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
@ -91,6 +86,57 @@ public class SimpleChildQuerySearchTests extends AbstractSharedClusterTest {
.execute().actionGet(); .execute().actionGet();
assertThat("Failures " + Arrays.toString(searchResponse.getShardFailures()), searchResponse.getShardFailures().length, equalTo(0)); assertThat("Failures " + Arrays.toString(searchResponse.getShardFailures()), searchResponse.getShardFailures().length, equalTo(0));
assertThat(searchResponse.getHits().totalHits(), equalTo(1l)); assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1"));
searchResponse = client().prepareSearch("test")
.setQuery(
filteredQuery(
matchAllQuery(),
hasParentFilter(
"parent",
termFilter("p_field", "p_value1")
)
)
).execute().actionGet();
assertThat("Failures " + Arrays.toString(searchResponse.getShardFailures()), searchResponse.getShardFailures().length, equalTo(0));
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("c1"));
searchResponse = client().prepareSearch("test")
.setQuery(
filteredQuery(
matchAllQuery(),
hasParentFilter(
"child",
termFilter("c_field", "c_value1")
)
)
).execute().actionGet();
assertThat("Failures " + Arrays.toString(searchResponse.getShardFailures()), searchResponse.getShardFailures().length, equalTo(0));
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("gc1"));
searchResponse = client().prepareSearch("test")
.setQuery(
hasParentQuery(
"parent",
termQuery("p_field", "p_value1")
)
).execute().actionGet();
assertThat("Failures " + Arrays.toString(searchResponse.getShardFailures()), searchResponse.getShardFailures().length, equalTo(0));
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("c1"));
searchResponse = client().prepareSearch("test")
.setQuery(
hasParentQuery(
"child",
termQuery("c_field", "c_value1")
)
).execute().actionGet();
assertThat("Failures " + Arrays.toString(searchResponse.getShardFailures()), searchResponse.getShardFailures().length, equalTo(0));
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("gc1"));
} }