Added better error handling for has_child, has_parent and top_children.
If has_parent, has_child or top_children are executed incorrectly then a better exception is thrown. This gives a better error description when one of these queries or filters is being used in count api. Closes #2261
This commit is contained in:
parent
2275b82549
commit
d5aa35e0ea
|
@ -39,6 +39,7 @@ import org.elasticsearch.index.service.IndexService;
|
|||
import org.elasticsearch.index.shard.service.IndexShard;
|
||||
import org.elasticsearch.indices.IndicesService;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.search.SearchShardTarget;
|
||||
import org.elasticsearch.search.internal.InternalSearchRequest;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
import org.elasticsearch.search.query.QueryPhaseExecutionException;
|
||||
|
@ -145,9 +146,10 @@ public class TransportCountAction extends TransportBroadcastOperationAction<Coun
|
|||
IndexService indexService = indicesService.indexServiceSafe(request.index());
|
||||
IndexShard indexShard = indexService.shardSafe(request.shardId());
|
||||
|
||||
SearchShardTarget shardTarget = new SearchShardTarget(clusterService.localNode().id(), request.index(), request.shardId());
|
||||
SearchContext context = new SearchContext(0,
|
||||
new InternalSearchRequest().types(request.types()).filteringAliases(request.filteringAliases()),
|
||||
null, indexShard.searcher(), indexService, indexShard,
|
||||
shardTarget, indexShard.searcher(), indexService, indexShard,
|
||||
scriptService);
|
||||
SearchContext.setCurrent(context);
|
||||
|
||||
|
|
|
@ -107,6 +107,10 @@ public abstract class HasChildFilter extends Filter implements ScopePhase.Collec
|
|||
}
|
||||
|
||||
public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
|
||||
if (parentDocs == null) {
|
||||
throw new ElasticSearchIllegalStateException("has_child filter/query hasn't executed properly");
|
||||
}
|
||||
|
||||
// ok to return null
|
||||
return parentDocs.get(reader.getCoreCacheKey());
|
||||
}
|
||||
|
@ -135,6 +139,10 @@ public abstract class HasChildFilter extends Filter implements ScopePhase.Collec
|
|||
}
|
||||
|
||||
public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
|
||||
if (collectedUids == null) {
|
||||
throw new ElasticSearchIllegalStateException("has_child filter/query hasn't executed properly");
|
||||
}
|
||||
|
||||
IdReaderTypeCache idReaderTypeCache = searchContext.idCache().reader(reader).type(parentType);
|
||||
return new ParentDocSet(reader, collectedUids, idReaderTypeCache);
|
||||
}
|
||||
|
|
|
@ -105,6 +105,10 @@ public abstract class HasParentFilter extends Filter implements ScopePhase.Colle
|
|||
}
|
||||
|
||||
public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
|
||||
if (parents == null) {
|
||||
throw new ElasticSearchIllegalStateException("has_parent filter/query hasn't executed properly");
|
||||
}
|
||||
|
||||
IdReaderTypeCache idReaderTypeCache = context.idCache().reader(reader).type(parentType);
|
||||
return new ChildrenDocSet(reader, parents, idReaderTypeCache);
|
||||
}
|
||||
|
@ -181,6 +185,10 @@ public abstract class HasParentFilter extends Filter implements ScopePhase.Colle
|
|||
}
|
||||
|
||||
public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
|
||||
if (parentDocs == null) {
|
||||
throw new ElasticSearchIllegalStateException("has_parent filter/query hasn't executed properly");
|
||||
}
|
||||
|
||||
return new ChildrenDocSet(reader, parentDocs, context, parentType);
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,9 @@ public class TopChildrenQuery extends Query implements ScopePhase.TopDocsPhase {
|
|||
|
||||
private int numHits = 0;
|
||||
|
||||
// Need to know if this query is properly used, otherwise the results are unexpected for example in the count api
|
||||
private boolean properlyInvoked = false;
|
||||
|
||||
// Note, the query is expected to already be filtered to only child type docs
|
||||
public TopChildrenQuery(Query query, String scope, String childType, String parentType, ScoreType scoreType, int factor, int incrementalFactor) {
|
||||
this.query = query;
|
||||
|
@ -97,6 +100,7 @@ public class TopChildrenQuery extends Query implements ScopePhase.TopDocsPhase {
|
|||
|
||||
@Override
|
||||
public void clear() {
|
||||
properlyInvoked = true;
|
||||
parentDocs = null;
|
||||
numHits = 0;
|
||||
}
|
||||
|
@ -202,6 +206,10 @@ public class TopChildrenQuery extends Query implements ScopePhase.TopDocsPhase {
|
|||
|
||||
@Override
|
||||
public Weight createWeight(Searcher searcher) throws IOException {
|
||||
if (!properlyInvoked) {
|
||||
throw new ElasticSearchIllegalStateException("top_children query hasn't executed properly");
|
||||
}
|
||||
|
||||
if (parentDocs != null) {
|
||||
return new ParentWeight(searcher, query.weight(searcher));
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.test.integration.search.child;
|
||||
|
||||
import org.elasticsearch.action.count.CountResponse;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.action.search.SearchType;
|
||||
import org.elasticsearch.action.search.ShardSearchFailure;
|
||||
|
@ -705,4 +706,43 @@ public class SimpleChildQuerySearchTests extends AbstractNodesTests {
|
|||
assertThat(searchResponse.hits().getAt(0).id(), equalTo("p2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountApiUsage() throws Exception {
|
||||
client.admin().indices().prepareDelete().execute().actionGet();
|
||||
|
||||
client.admin().indices().prepareCreate("test").setSettings(ImmutableSettings.settingsBuilder().put("index.number_of_shards", 1)).execute().actionGet();
|
||||
client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
|
||||
client.admin().indices().preparePutMapping("test").setType("child").setSource(XContentFactory.jsonBuilder().startObject().startObject("type")
|
||||
.startObject("_parent").field("type", "parent").endObject()
|
||||
.endObject().endObject()).execute().actionGet();
|
||||
|
||||
String parentId = "p1";
|
||||
client.prepareIndex("test", "parent", parentId)
|
||||
.setSource("p_field", "p_value1")
|
||||
.execute().actionGet();
|
||||
client.prepareIndex("test", "child", parentId + "_c1")
|
||||
.setSource("c_field1", parentId)
|
||||
.setParent(parentId)
|
||||
.execute().actionGet();
|
||||
client.admin().indices().prepareRefresh().execute().actionGet();
|
||||
|
||||
CountResponse countResponse = client.prepareCount("test")
|
||||
.setQuery(topChildrenQuery("child", termQuery("c_field1", "1")))
|
||||
.execute().actionGet();
|
||||
assertThat(countResponse.failedShards(), equalTo(1));
|
||||
assertThat(countResponse.shardFailures().get(0).reason().contains("top_children query hasn't executed properly"), equalTo(true));
|
||||
|
||||
countResponse = client.prepareCount("test")
|
||||
.setQuery(hasChildQuery("child", termQuery("c_field1", "2")).executionType(getExecutionMethod()))
|
||||
.execute().actionGet();
|
||||
assertThat(countResponse.failedShards(), equalTo(1));
|
||||
assertThat(countResponse.shardFailures().get(0).reason().contains("has_child filter/query hasn't executed properly"), equalTo(true));
|
||||
|
||||
countResponse = client.prepareCount("test")
|
||||
.setQuery(hasParentQuery("parent", termQuery("p_field1", "1")).executionType(getExecutionMethod()))
|
||||
.execute().actionGet();
|
||||
assertThat(countResponse.failedShards(), equalTo(1));
|
||||
assertThat(countResponse.shardFailures().get(0).reason().contains("has_parent filter/query hasn't executed properly"), equalTo(true));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue