inner hits: Query and top level inner hit definitions shouldn't overwrite each other.

Closes #16218
This commit is contained in:
Martijn van Groningen 2016-01-26 12:39:41 +01:00
parent b039360d2e
commit 6c34452409
15 changed files with 58 additions and 110 deletions

View File

@ -236,13 +236,7 @@ public class QueryShardContext {
throw new QueryShardException(this, "inner_hits unsupported");
}
InnerHitsContext innerHitsContext;
if (sc.innerHits() == null) {
innerHitsContext = new InnerHitsContext(new HashMap<>());
sc.innerHits(innerHitsContext);
} else {
innerHitsContext = sc.innerHits();
}
InnerHitsContext innerHitsContext = sc.innerHits();
innerHitsContext.addInnerHitDefinition(name, context);
}

View File

@ -674,11 +674,6 @@ public class PercolateContext extends SearchContext {
throw new UnsupportedOperationException();
}
@Override
public void innerHits(InnerHitsContext innerHitsContext) {
throw new UnsupportedOperationException();
}
@Override
public InnerHitsContext innerHits() {
throw new UnsupportedOperationException();

View File

@ -56,6 +56,7 @@ import org.elasticsearch.search.internal.InternalSearchHit;
import org.elasticsearch.search.internal.SearchContext;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
@ -64,6 +65,10 @@ public final class InnerHitsContext {
private final Map<String, BaseInnerHits> innerHits;
public InnerHitsContext() {
this.innerHits = new HashMap<>();
}
public InnerHitsContext(Map<String, BaseInnerHits> innerHits) {
this.innerHits = innerHits;
}
@ -73,9 +78,19 @@ public final class InnerHitsContext {
}
public void addInnerHitDefinition(String name, BaseInnerHits innerHit) {
if (innerHits.containsKey(name)) {
throw new IllegalArgumentException("inner_hit definition with the name [" + name + "] already exists. Use a different inner_hit name");
}
innerHits.put(name, innerHit);
}
public void addInnerHitDefinitions(Map<String, BaseInnerHits> innerHits) {
for (Map.Entry<String, BaseInnerHits> entry : innerHits.entrySet()) {
addInnerHitDefinition(entry.getKey(), entry.getValue());
}
}
public static abstract class BaseInnerHits extends FilteredSearchContext {
protected final ParsedQuery query;

View File

@ -63,7 +63,7 @@ public class InnerHitsFetchSubPhase implements FetchSubPhase {
@Override
public boolean hitExecutionNeeded(SearchContext context) {
return context.innerHits() != null;
return context.innerHits() != null && context.innerHits().getInnerHits().size() > 0;
}
@Override

View File

@ -61,9 +61,10 @@ public class InnerHitsParseElement implements SearchParseElement {
public void parse(XContentParser parser, SearchContext searchContext) throws Exception {
QueryShardContext context = searchContext.indexShard().getQueryShardContext();
context.reset(parser);
Map<String, InnerHitsContext.BaseInnerHits> innerHitsMap = parseInnerHits(parser, context, searchContext);
if (innerHitsMap != null) {
searchContext.innerHits(new InnerHitsContext(innerHitsMap));
Map<String, InnerHitsContext.BaseInnerHits> topLevelInnerHits = parseInnerHits(parser, context, searchContext);
if (topLevelInnerHits != null) {
InnerHitsContext innerHitsContext = searchContext.innerHits();
innerHitsContext.addInnerHitDefinitions(topLevelInnerHits);
}
}

View File

@ -146,7 +146,6 @@ public class DefaultSearchContext extends SearchContext {
private volatile long keepAlive;
private final long originNanoTime = System.nanoTime();
private volatile long lastAccessTime = -1;
private InnerHitsContext innerHitsContext;
private Profilers profilers;
private final Map<String, FetchSubPhaseContext> subPhaseContexts = new HashMap<>();
@ -761,16 +760,6 @@ public class DefaultSearchContext extends SearchContext {
return timeEstimateCounter;
}
@Override
public void innerHits(InnerHitsContext innerHitsContext) {
this.innerHitsContext = innerHitsContext;
}
@Override
public InnerHitsContext innerHits() {
return innerHitsContext;
}
@Override
public Map<Class<?>, Collector> queryCollectors() {
return queryCollectors;

View File

@ -177,11 +177,6 @@ public abstract class FilteredSearchContext extends SearchContext {
in.highlight(highlight);
}
@Override
public void innerHits(InnerHitsContext innerHitsContext) {
in.innerHits(innerHitsContext);
}
@Override
public InnerHitsContext innerHits() {
return in.innerHits();

View File

@ -86,6 +86,7 @@ public abstract class SearchContext implements Releasable {
private Map<Lifetime, List<Releasable>> clearables = null;
private final AtomicBoolean closed = new AtomicBoolean(false);
private InnerHitsContext innerHitsContext;
protected final ParseFieldMatcher parseFieldMatcher;
@ -168,9 +169,12 @@ public abstract class SearchContext implements Releasable {
public abstract void highlight(SearchContextHighlight highlight);
public abstract void innerHits(InnerHitsContext innerHitsContext);
public abstract InnerHitsContext innerHits();
public InnerHitsContext innerHits() {
if (innerHitsContext == null) {
innerHitsContext = new InnerHitsContext();
}
return innerHitsContext;
}
public abstract SuggestionSearchContext suggest();

View File

@ -66,8 +66,6 @@ public class SubSearchContext extends FilteredSearchContext {
private boolean trackScores;
private boolean version;
private InnerHitsContext innerHitsContext;
public SubSearchContext(SearchContext context) {
super(context);
this.fetchSearchResult = new FetchSearchResult();
@ -326,13 +324,4 @@ public class SubSearchContext extends FilteredSearchContext {
throw new UnsupportedOperationException("Not supported");
}
@Override
public void innerHits(InnerHitsContext innerHitsContext) {
this.innerHitsContext = innerHitsContext;
}
@Override
public InnerHitsContext innerHits() {
return innerHitsContext;
}
}

View File

@ -85,18 +85,6 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
final MapperService mapperService = queryShardContext().getMapperService();
final IndexFieldDataService fieldData = indexFieldDataService();
TestSearchContext testSearchContext = new TestSearchContext() {
private InnerHitsContext context;
@Override
public void innerHits(InnerHitsContext innerHitsContext) {
context = innerHitsContext;
}
@Override
public InnerHitsContext innerHits() {
return context;
}
@Override
public MapperService mapperService() {
@ -149,7 +137,7 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
assertEquals(innerHits.sort().getSort().length, 1);
assertEquals(innerHits.sort().getSort()[0].getField(), STRING_FIELD_NAME);
} else {
assertNull(SearchContext.current().innerHits());
assertThat(SearchContext.current().innerHits().getInnerHits().size(), equalTo(0));
}
}
}

View File

@ -80,18 +80,6 @@ public class HasParentQueryBuilderTests extends AbstractQueryTestCase<HasParentQ
final MapperService mapperService = queryShardContext().getMapperService();
final IndexFieldDataService fieldData = indexFieldDataService();
TestSearchContext testSearchContext = new TestSearchContext() {
private InnerHitsContext context;
@Override
public void innerHits(InnerHitsContext innerHitsContext) {
context = innerHitsContext;
}
@Override
public InnerHitsContext innerHits() {
return context;
}
@Override
public MapperService mapperService() {
@ -139,7 +127,7 @@ public class HasParentQueryBuilderTests extends AbstractQueryTestCase<HasParentQ
assertEquals(innerHits.sort().getSort().length, 1);
assertEquals(innerHits.sort().getSort()[0].getField(), STRING_FIELD_NAME);
} else {
assertNull(SearchContext.current().innerHits());
assertThat(SearchContext.current().innerHits().getInnerHits().size(), equalTo(0));
}
}
}

View File

@ -27,16 +27,17 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.index.fielddata.IndexFieldDataService;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.query.support.QueryInnerHits;
import org.elasticsearch.search.fetch.innerhits.InnerHitsBuilder;
import org.elasticsearch.search.fetch.innerhits.InnerHitsContext;
import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.test.TestSearchContext;
import org.elasticsearch.index.query.support.QueryInnerHits;
import org.elasticsearch.search.fetch.innerhits.InnerHitsBuilder;
import org.elasticsearch.search.fetch.innerhits.InnerHitsContext;
import java.io.IOException;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.equalTo;
public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBuilder> {
@ -60,18 +61,6 @@ public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBu
final MapperService mapperService = queryShardContext().getMapperService();
final IndexFieldDataService fieldData = indexFieldDataService();
TestSearchContext testSearchContext = new TestSearchContext() {
private InnerHitsContext context;
@Override
public void innerHits(InnerHitsContext innerHitsContext) {
context = innerHitsContext;
}
@Override
public InnerHitsContext innerHits() {
return context;
}
@Override
public MapperService mapperService() {
@ -119,7 +108,7 @@ public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBu
assertEquals(innerHits.sort().getSort().length, 1);
assertEquals(innerHits.sort().getSort()[0].getField(), STRING_FIELD_NAME);
} else {
assertNull(SearchContext.current().innerHits());
assertThat(SearchContext.current().innerHits().getInnerHits().size(), equalTo(0));
}
}
}

View File

@ -65,18 +65,6 @@ public class ParentIdQueryBuilderTests extends AbstractQueryTestCase<ParentIdQue
final MapperService mapperService = queryShardContext().getMapperService();
final IndexFieldDataService fieldData = indexFieldDataService();
TestSearchContext testSearchContext = new TestSearchContext() {
private InnerHitsContext context;
@Override
public void innerHits(InnerHitsContext innerHitsContext) {
context = innerHitsContext;
}
@Override
public InnerHitsContext innerHits() {
return context;
}
@Override
public MapperService mapperService() {

View File

@ -28,6 +28,8 @@ import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.HasChildQueryBuilder;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.support.QueryInnerHits;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.MockScriptEngine;
@ -1219,4 +1221,25 @@ public class InnerHitsIT extends ESIntegTestCase {
assertHitCount(response, 1);
}
public void testTopLevelInnerHitsWithQueryInnerHits() throws Exception {
// top level inner hits shouldn't overwrite query inner hits definitions
assertAcked(prepareCreate("index1").addMapping("child", "_parent", "type=parent"));
List<IndexRequestBuilder> requests = new ArrayList<>();
requests.add(client().prepareIndex("index1", "parent", "1").setSource("{}"));
requests.add(client().prepareIndex("index1", "child", "2").setParent("1").setSource("{}"));
indexRandom(true, requests);
InnerHitsBuilder innerHitsBuilder = new InnerHitsBuilder();
innerHitsBuilder.addParentChildInnerHits("my-inner-hit", "child", new InnerHitsBuilder.InnerHit());
SearchResponse response = client().prepareSearch("index1")
.setQuery(hasChildQuery("child", new MatchAllQueryBuilder()).innerHit(new QueryInnerHits()))
.innerHits(innerHitsBuilder)
.get();
assertHitCount(response, 1);
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(2));
assertThat(response.getHits().getAt(0).getInnerHits().get("child").getAt(0).getId(), equalTo("2"));
assertThat(response.getHits().getAt(0).getInnerHits().get("my-inner-hit").getAt(0).getId(), equalTo("2"));
}
}

View File

@ -582,16 +582,6 @@ public class TestSearchContext extends SearchContext {
return timeEstimateCounter;
}
@Override
public void innerHits(InnerHitsContext innerHitsContext) {
throw new UnsupportedOperationException();
}
@Override
public InnerHitsContext innerHits() {
throw new UnsupportedOperationException();
}
@Override
public Profilers getProfilers() {
return null; // no profiling