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 java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.HashSet;
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");
}
List<String> parentTypes = new ArrayList<String>(2);
Set<String> parentTypes = new HashSet<String>(5);
parentTypes.add(parentType);
for (DocumentMapper documentMapper : parseContext.mapperService()) {
ParentFieldMapper parentFieldMapper = documentMapper.parentFieldMapper();
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;
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);
} else {
XBooleanFilter parentsFilter = new XBooleanFilter();

View File

@ -37,8 +37,8 @@ import org.elasticsearch.index.search.child.ParentQuery;
import org.elasticsearch.search.internal.SearchContext;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.HashSet;
import java.util.Set;
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.");
}
List<String> parentTypes = new ArrayList<String>(2);
Set<String> parentTypes = new HashSet<String>(5);
parentTypes.add(parentType);
for (DocumentMapper documentMapper : parseContext.mapperService()) {
ParentFieldMapper parentFieldMapper = documentMapper.parentFieldMapper();
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;
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);
} else {
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.SortOrder;
import org.elasticsearch.test.integration.AbstractSharedClusterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.*;
import static com.google.common.collect.Maps.newHashMap;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
@ -91,6 +86,57 @@ public class SimpleChildQuerySearchTests extends AbstractSharedClusterTest {
.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("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"));
}