Skip to content

Commit

Permalink
Throw if two inner_hits have the same name (#37645)
Browse files Browse the repository at this point in the history
This change throws an error if two inner_hits have the same name

Closes #37584
  • Loading branch information
dvehar authored and jimczi committed Feb 1, 2019
1 parent 35ed137 commit c1c4aba
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,13 @@ protected QueryBuilder doRewrite(QueryRewriteContext queryShardContext) throws I
@Override
protected void extractInnerHitBuilders(Map<String, InnerHitContextBuilder> innerHits) {
if (innerHitBuilder != null) {
String name = innerHitBuilder.getName() != null ? innerHitBuilder.getName() : type;
if (innerHits.containsKey(name)) {
throw new IllegalArgumentException("[inner_hits] already contains an entry for key [" + name + "]");
}

Map<String, InnerHitContextBuilder> children = new HashMap<>();
InnerHitContextBuilder.extractInnerHits(query, children);
String name = innerHitBuilder.getName() != null ? innerHitBuilder.getName() : type;
InnerHitContextBuilder innerHitContextBuilder =
new ParentChildInnerHitContextBuilder(type, true, query, innerHitBuilder, children);
innerHits.put(name, innerHitContextBuilder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,13 @@ protected QueryBuilder doRewrite(QueryRewriteContext queryShardContext) throws I
@Override
protected void extractInnerHitBuilders(Map<String, InnerHitContextBuilder> innerHits) {
if (innerHitBuilder != null) {
String name = innerHitBuilder.getName() != null ? innerHitBuilder.getName() : type;
if (innerHits.containsKey(name)) {
throw new IllegalArgumentException("[inner_hits] already contains an entry for key [" + name + "]");
}

Map<String, InnerHitContextBuilder> children = new HashMap<>();
InnerHitContextBuilder.extractInnerHits(query, children);
String name = innerHitBuilder.getName() != null ? innerHitBuilder.getName() : type;
InnerHitContextBuilder innerHitContextBuilder =
new ParentChildInnerHitContextBuilder(type, false, query, innerHitBuilder, children);
innerHits.put(name, innerHitContextBuilder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,4 +367,12 @@ public void testIgnoreUnmappedWithRewrite() throws IOException {
assertThat(query, notNullValue());
assertThat(query, instanceOf(MatchNoDocsQuery.class));
}

public void testExtractInnerHitBuildersWithDuplicate() {
final HasChildQueryBuilder queryBuilder
= new HasChildQueryBuilder(CHILD_DOC, new WrapperQueryBuilder(new MatchAllQueryBuilder().toString()), ScoreMode.None);
queryBuilder.innerHit(new InnerHitBuilder("some_name"));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> InnerHitContextBuilder.extractInnerHits(queryBuilder, Collections.singletonMap("some_name", null)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -268,4 +268,12 @@ public void testIgnoreUnmappedWithRewrite() throws IOException {
assertThat(query, notNullValue());
assertThat(query, instanceOf(MatchNoDocsQuery.class));
}

public void testExtractInnerHitBuildersWithDuplicate() {
final HasParentQueryBuilder queryBuilder
= new HasParentQueryBuilder(CHILD_DOC, new WrapperQueryBuilder(new MatchAllQueryBuilder().toString()), false);
queryBuilder.innerHit(new InnerHitBuilder("some_name"));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> InnerHitContextBuilder.extractInnerHits(queryBuilder, Collections.singletonMap("some_name", null)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -317,10 +317,14 @@ protected QueryBuilder doRewrite(QueryRewriteContext queryRewriteContext) throws
@Override
public void extractInnerHitBuilders(Map<String, InnerHitContextBuilder> innerHits) {
if (innerHitBuilder != null) {
String name = innerHitBuilder.getName() != null ? innerHitBuilder.getName() : path;
if (innerHits.containsKey(name)) {
throw new IllegalArgumentException("[inner_hits] already contains an entry for key [" + name + "]");
}

Map<String, InnerHitContextBuilder> children = new HashMap<>();
InnerHitContextBuilder.extractInnerHits(query, children);
InnerHitContextBuilder innerHitContextBuilder = new NestedInnerHitContextBuilder(path, query, innerHitBuilder, children);
String name = innerHitBuilder.getName() != null ? innerHitBuilder.getName() : path;
innerHits.put(name, innerHitContextBuilder);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.hamcrest.Matchers;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

Expand Down Expand Up @@ -354,4 +355,12 @@ public void testBuildIgnoreUnmappedNestQuery() throws Exception {
nestedContextBuilder.build(searchContext, innerHitsContext);
assertThat(innerHitsContext.getInnerHits().size(), Matchers.equalTo(0));
}

public void testExtractInnerHitBuildersWithDuplicate() {
final NestedQueryBuilder queryBuilder
= new NestedQueryBuilder("path", new WrapperQueryBuilder(new MatchAllQueryBuilder().toString()), ScoreMode.None);
queryBuilder.innerHit(new InnerHitBuilder("some_name"));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> InnerHitContextBuilder.extractInnerHits(queryBuilder,Collections.singletonMap("some_name", null)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.InnerHitBuilder;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.aggregations.Aggregator.SubAggCollectionMode;
import org.elasticsearch.search.aggregations.InternalAggregation;
import org.elasticsearch.search.aggregations.bucket.filter.Filter;
Expand All @@ -46,6 +49,7 @@
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS;
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.index.query.QueryBuilders.nestedQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
Expand All @@ -57,6 +61,7 @@
import static org.elasticsearch.search.aggregations.AggregationBuilders.sum;
import static org.elasticsearch.search.aggregations.AggregationBuilders.terms;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFailures;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse;
Expand Down Expand Up @@ -674,4 +679,46 @@ public void testFilterAggInsideNestedAgg() throws Exception {
numStringParams = bucket.getAggregations().get("num_string_params");
assertThat(numStringParams.getDocCount(), equalTo(0L));
}

public void testExtractInnerHitBuildersWithDuplicateHitName() throws Exception {
assertAcked(
prepareCreate("idxduplicatehitnames")
.setSettings(Settings.builder().put(SETTING_NUMBER_OF_SHARDS, 1).put(SETTING_NUMBER_OF_REPLICAS, 0))
.addMapping("product", "categories", "type=keyword", "name", "type=text", "property", "type=nested")
);
ensureGreen("idxduplicatehitnames");

SearchRequestBuilder searchRequestBuilder = client()
.prepareSearch("idxduplicatehitnames")
.setQuery(boolQuery()
.should(nestedQuery("property", termQuery("property.id", 1D), ScoreMode.None).innerHit(new InnerHitBuilder("ih1")))
.should(nestedQuery("property", termQuery("property.id", 1D), ScoreMode.None).innerHit(new InnerHitBuilder("ih2")))
.should(nestedQuery("property", termQuery("property.id", 1D), ScoreMode.None).innerHit(new InnerHitBuilder("ih1"))));

assertFailures(
searchRequestBuilder,
RestStatus.BAD_REQUEST,
containsString("[inner_hits] already contains an entry for key [ih1]"));
}

public void testExtractInnerHitBuildersWithDuplicatePath() throws Exception {
assertAcked(
prepareCreate("idxnullhitnames")
.setSettings(Settings.builder().put(SETTING_NUMBER_OF_SHARDS, 1).put(SETTING_NUMBER_OF_REPLICAS, 0))
.addMapping("product", "categories", "type=keyword", "name", "type=text", "property", "type=nested")
);
ensureGreen("idxnullhitnames");

SearchRequestBuilder searchRequestBuilder = client()
.prepareSearch("idxnullhitnames")
.setQuery(boolQuery()
.should(nestedQuery("property", termQuery("property.id", 1D), ScoreMode.None).innerHit(new InnerHitBuilder()))
.should(nestedQuery("property", termQuery("property.id", 1D), ScoreMode.None).innerHit(new InnerHitBuilder()))
.should(nestedQuery("property", termQuery("property.id", 1D), ScoreMode.None).innerHit(new InnerHitBuilder())));

assertFailures(
searchRequestBuilder,
RestStatus.BAD_REQUEST,
containsString("[inner_hits] already contains an entry for key [property]"));
}
}

0 comments on commit c1c4aba

Please sign in to comment.