inner hits: Query and top level inner hit definitions shouldn't overwrite each other.
Closes #16218
This commit is contained in:
parent
b039360d2e
commit
6c34452409
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue