Skip to content

Commit 9d1184f

Browse files
committed
throw if two inner_hits have the same name
Fixes #37584
1 parent 68149b6 commit 9d1184f

File tree

7 files changed

+80
-1
lines changed

7 files changed

+80
-1
lines changed

modules/parent-join/src/main/java/org/elasticsearch/join/query/HasChildQueryBuilder.java

+4
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,10 @@ protected QueryBuilder doRewrite(QueryRewriteContext queryShardContext) throws I
460460
@Override
461461
protected void extractInnerHitBuilders(Map<String, InnerHitContextBuilder> innerHits) {
462462
if (innerHitBuilder != null) {
463+
if (innerHits.containsKey(innerHitBuilder.getName())) {
464+
throw new IllegalArgumentException("innerHits already contains an entry for key [" + innerHitBuilder.getName() + "]");
465+
}
466+
463467
Map<String, InnerHitContextBuilder> children = new HashMap<>();
464468
InnerHitContextBuilder.extractInnerHits(query, children);
465469
String name = innerHitBuilder.getName() != null ? innerHitBuilder.getName() : type;

modules/parent-join/src/main/java/org/elasticsearch/join/query/HasParentQueryBuilder.java

+4
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,10 @@ protected QueryBuilder doRewrite(QueryRewriteContext queryShardContext) throws I
285285
@Override
286286
protected void extractInnerHitBuilders(Map<String, InnerHitContextBuilder> innerHits) {
287287
if (innerHitBuilder != null) {
288+
if (innerHits.containsKey(innerHitBuilder.getName())) {
289+
throw new IllegalArgumentException("innerHits already contains an entry for key [" + innerHitBuilder.getName() + "]");
290+
}
291+
288292
Map<String, InnerHitContextBuilder> children = new HashMap<>();
289293
InnerHitContextBuilder.extractInnerHits(query, children);
290294
String name = innerHitBuilder.getName() != null ? innerHitBuilder.getName() : type;

modules/parent-join/src/test/java/org/elasticsearch/join/query/HasChildQueryBuilderTests.java

+7
Original file line numberDiff line numberDiff line change
@@ -367,4 +367,11 @@ public void testIgnoreUnmappedWithRewrite() throws IOException {
367367
assertThat(query, notNullValue());
368368
assertThat(query, instanceOf(MatchNoDocsQuery.class));
369369
}
370+
371+
public void testExtractInnerHitBuildersWithDuplicate() {
372+
final HasChildQueryBuilder queryBuilder
373+
= new HasChildQueryBuilder(CHILD_DOC, new WrapperQueryBuilder(new MatchAllQueryBuilder().toString()), ScoreMode.None);
374+
queryBuilder.innerHit(new InnerHitBuilder("some_name"));
375+
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> InnerHitContextBuilder.extractInnerHits(queryBuilder, Collections.singletonMap("some_name", null)));
376+
}
370377
}

modules/parent-join/src/test/java/org/elasticsearch/join/query/HasParentQueryBuilderTests.java

+7
Original file line numberDiff line numberDiff line change
@@ -268,4 +268,11 @@ public void testIgnoreUnmappedWithRewrite() throws IOException {
268268
assertThat(query, notNullValue());
269269
assertThat(query, instanceOf(MatchNoDocsQuery.class));
270270
}
271+
272+
public void testExtractInnerHitBuildersWithDuplicate() {
273+
final HasParentQueryBuilder queryBuilder
274+
= new HasParentQueryBuilder(CHILD_DOC, new WrapperQueryBuilder(new MatchAllQueryBuilder().toString()), false);
275+
queryBuilder.innerHit(new InnerHitBuilder("some_name"));
276+
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> InnerHitContextBuilder.extractInnerHits(queryBuilder, Collections.singletonMap("some_name", null)));
277+
}
271278
}

server/src/main/java/org/elasticsearch/index/query/NestedQueryBuilder.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ private NestedQueryBuilder(String path, QueryBuilder query, ScoreMode scoreMode,
9494
*/
9595
public NestedQueryBuilder(StreamInput in) throws IOException {
9696
super(in);
97+
9798
path = in.readString();
9899
scoreMode = ScoreMode.values()[in.readVInt()];
99100
query = in.readNamedWriteable(QueryBuilder.class);
@@ -317,10 +318,14 @@ protected QueryBuilder doRewrite(QueryRewriteContext queryRewriteContext) throws
317318
@Override
318319
public void extractInnerHitBuilders(Map<String, InnerHitContextBuilder> innerHits) {
319320
if (innerHitBuilder != null) {
321+
if (innerHits.containsKey(innerHitBuilder.getName())) {
322+
throw new IllegalArgumentException("innerHits already contains an entry for key [" + innerHitBuilder.getName() + "]");
323+
}
324+
320325
Map<String, InnerHitContextBuilder> children = new HashMap<>();
321326
InnerHitContextBuilder.extractInnerHits(query, children);
322-
InnerHitContextBuilder innerHitContextBuilder = new NestedInnerHitContextBuilder(path, query, innerHitBuilder, children);
323327
String name = innerHitBuilder.getName() != null ? innerHitBuilder.getName() : path;
328+
InnerHitContextBuilder innerHitContextBuilder = new NestedInnerHitContextBuilder(path, query, innerHitBuilder, children);
324329
innerHits.put(name, innerHitContextBuilder);
325330
}
326331
}

server/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java

+9
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.hamcrest.Matchers;
4242

4343
import java.io.IOException;
44+
import java.util.Collections;
4445
import java.util.HashMap;
4546
import java.util.Map;
4647

@@ -354,4 +355,12 @@ public void testBuildIgnoreUnmappedNestQuery() throws Exception {
354355
nestedContextBuilder.build(searchContext, innerHitsContext);
355356
assertThat(innerHitsContext.getInnerHits().size(), Matchers.equalTo(0));
356357
}
358+
359+
public void testExtractInnerHitBuildersWithDuplicate() {
360+
final NestedQueryBuilder queryBuilder
361+
= new NestedQueryBuilder("path", new WrapperQueryBuilder(new MatchAllQueryBuilder().toString()), ScoreMode.None);
362+
queryBuilder.innerHit(new InnerHitBuilder("some_name"));
363+
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
364+
() -> InnerHitContextBuilder.extractInnerHits(queryBuilder,Collections.singletonMap("some_name", null)));
365+
}
357366
}

server/src/test/java/org/elasticsearch/search/aggregations/bucket/NestedIT.java

+43
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@
2121
import org.apache.lucene.search.join.ScoreMode;
2222
import org.elasticsearch.action.index.IndexRequestBuilder;
2323
import org.elasticsearch.action.search.SearchPhaseExecutionException;
24+
import org.elasticsearch.action.search.SearchRequestBuilder;
2425
import org.elasticsearch.action.search.SearchResponse;
2526
import org.elasticsearch.common.settings.Settings;
2627
import org.elasticsearch.common.xcontent.XContentBuilder;
2728
import org.elasticsearch.common.xcontent.XContentType;
29+
import org.elasticsearch.index.query.InnerHitBuilder;
30+
import org.elasticsearch.rest.RestStatus;
2831
import org.elasticsearch.search.aggregations.Aggregator.SubAggCollectionMode;
2932
import org.elasticsearch.search.aggregations.InternalAggregation;
3033
import org.elasticsearch.search.aggregations.bucket.filter.Filter;
@@ -46,6 +49,7 @@
4649
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS;
4750
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS;
4851
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
52+
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
4953
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
5054
import static org.elasticsearch.index.query.QueryBuilders.nestedQuery;
5155
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
@@ -57,6 +61,7 @@
5761
import static org.elasticsearch.search.aggregations.AggregationBuilders.sum;
5862
import static org.elasticsearch.search.aggregations.AggregationBuilders.terms;
5963
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
64+
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertFailures;
6065
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
6166
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
6267
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse;
@@ -674,4 +679,42 @@ public void testFilterAggInsideNestedAgg() throws Exception {
674679
numStringParams = bucket.getAggregations().get("num_string_params");
675680
assertThat(numStringParams.getDocCount(), equalTo(0L));
676681
}
682+
683+
public void testExtractInnerHitBuildersWithDuplicateName() throws Exception {
684+
assertAcked(
685+
prepareCreate("idxduplicatehitnames")
686+
.setSettings(Settings.builder().put(SETTING_NUMBER_OF_SHARDS, 1).put(SETTING_NUMBER_OF_REPLICAS, 0))
687+
.addMapping("product", "categories", "type=keyword", "name", "type=text", "property", "type=nested")
688+
);
689+
ensureGreen("idxduplicatehitnames");
690+
691+
SearchRequestBuilder searchRequestBuilder = client()
692+
.prepareSearch("idxduplicatehitnames")
693+
.setQuery(boolQuery()
694+
.should(nestedQuery("property", termQuery("property.id", 1D), ScoreMode.None).innerHit(new InnerHitBuilder("ih1")))
695+
.should(nestedQuery("property", termQuery("property.id", 1D), ScoreMode.None).innerHit(new InnerHitBuilder("ih2")))
696+
.should(nestedQuery("property", termQuery("property.id", 1D), ScoreMode.None).innerHit(new InnerHitBuilder("ih1"))));
697+
698+
assertFailures(
699+
searchRequestBuilder,
700+
RestStatus.BAD_REQUEST,
701+
containsString("innerHits already contains an entry for key [ih1]"));
702+
}
703+
704+
public void testExtractInnerHitBuildersWithNullName() throws Exception {
705+
assertAcked(
706+
prepareCreate("idxnullhitnames")
707+
.setSettings(Settings.builder().put(SETTING_NUMBER_OF_SHARDS, 1).put(SETTING_NUMBER_OF_REPLICAS, 0))
708+
.addMapping("product", "categories", "type=keyword", "name", "type=text", "property", "type=nested")
709+
);
710+
ensureGreen("idxnullhitnames");
711+
712+
SearchResponse response = client().prepareSearch("idxnullhitnames")
713+
.setQuery(boolQuery()
714+
.should(nestedQuery("property", termQuery("property.id", 1D), ScoreMode.None).innerHit(new InnerHitBuilder()))
715+
.should(nestedQuery("property", termQuery("property.id", 1D), ScoreMode.None).innerHit(new InnerHitBuilder()))
716+
.should(nestedQuery("property", termQuery("property.id", 1D), ScoreMode.None).innerHit(new InnerHitBuilder()))
717+
).get();
718+
assertNoFailures(response);
719+
}
677720
}

0 commit comments

Comments
 (0)