inner hits: Don't inline inner hits if the query the inner hits is inlined into can't resolve mappings and ignore_unmapped has been set to true

Closes #21620
This commit is contained in:
Martijn van Groningen 2016-12-21 17:24:32 +01:00
parent 9a73a2efb3
commit b9a90eca20
11 changed files with 228 additions and 78 deletions

View File

@ -145,8 +145,8 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
return innerHitBuilder;
}
public HasChildQueryBuilder innerHit(InnerHitBuilder innerHit) {
this.innerHitBuilder = new InnerHitBuilder(Objects.requireNonNull(innerHit), query, type);
public HasChildQueryBuilder innerHit(InnerHitBuilder innerHit, boolean ignoreUnmapped) {
this.innerHitBuilder = new InnerHitBuilder(Objects.requireNonNull(innerHit), query, type, ignoreUnmapped);
return this;
}
@ -268,13 +268,13 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
}
}
HasChildQueryBuilder hasChildQueryBuilder = new HasChildQueryBuilder(childType, iqb, scoreMode);
if (innerHitBuilder != null) {
hasChildQueryBuilder.innerHit(innerHitBuilder);
}
hasChildQueryBuilder.minMaxChildren(minChildren, maxChildren);
hasChildQueryBuilder.queryName(queryName);
hasChildQueryBuilder.boost(boost);
hasChildQueryBuilder.ignoreUnmapped(ignoreUnmapped);
if (innerHitBuilder != null) {
hasChildQueryBuilder.innerHit(innerHitBuilder, ignoreUnmapped);
}
return hasChildQueryBuilder;
}
@ -318,7 +318,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
context.setTypes(previousTypes);
}
DocumentMapper childDocMapper = context.getMapperService().documentMapper(type);
DocumentMapper childDocMapper = context.documentMapper(type);
if (childDocMapper == null) {
if (ignoreUnmapped) {
return new MatchNoDocsQuery();

View File

@ -124,8 +124,8 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
return innerHit;
}
public HasParentQueryBuilder innerHit(InnerHitBuilder innerHit) {
this.innerHit = new InnerHitBuilder(innerHit, query, type);
public HasParentQueryBuilder innerHit(InnerHitBuilder innerHit, boolean ignoreUnmapped) {
this.innerHit = new InnerHitBuilder(innerHit, query, type, ignoreUnmapped);
return this;
}
@ -159,7 +159,7 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
context.setTypes(previousTypes);
}
DocumentMapper parentDocMapper = context.getMapperService().documentMapper(type);
DocumentMapper parentDocMapper = context.documentMapper(type);
if (parentDocMapper == null) {
if (ignoreUnmapped) {
return new MatchNoDocsQuery();
@ -276,7 +276,7 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
.queryName(queryName)
.boost(boost);
if (innerHits != null) {
queryBuilder.innerHit(innerHits);
queryBuilder.innerHit(innerHits, ignoreUnmapped);
}
return queryBuilder;
}

View File

@ -18,6 +18,7 @@
*/
package org.elasticsearch.index.query;
import org.elasticsearch.Version;
import org.elasticsearch.action.support.ToXContentToBytes;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.ParsingException;
@ -45,7 +46,6 @@ import org.elasticsearch.search.sort.SortBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -59,6 +59,7 @@ import static org.elasticsearch.common.xcontent.XContentParser.Token.END_OBJECT;
public final class InnerHitBuilder extends ToXContentToBytes implements Writeable {
public static final ParseField NAME_FIELD = new ParseField("name");
public static final ParseField IGNORE_UNMAPPED = new ParseField("ignore_unmapped");
public static final ParseField INNER_HITS_FIELD = new ParseField("inner_hits");
public static final QueryBuilder DEFAULT_INNER_HIT_QUERY = new MatchAllQueryBuilder();
@ -66,6 +67,7 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
static {
PARSER.declareString(InnerHitBuilder::setName, NAME_FIELD);
PARSER.declareBoolean((innerHitBuilder, value) -> innerHitBuilder.ignoreUnmapped = value, IGNORE_UNMAPPED);
PARSER.declareInt(InnerHitBuilder::setFrom, SearchSourceBuilder.FROM_FIELD);
PARSER.declareInt(InnerHitBuilder::setSize, SearchSourceBuilder.SIZE_FIELD);
PARSER.declareBoolean(InnerHitBuilder::setExplain, SearchSourceBuilder.EXPLAIN_FIELD);
@ -130,6 +132,7 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
private String name;
private String nestedPath;
private String parentChildType;
private boolean ignoreUnmapped;
private int from;
private int size = 3;
@ -151,6 +154,7 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
private InnerHitBuilder(InnerHitBuilder other) {
name = other.name;
this.ignoreUnmapped = other.ignoreUnmapped;
from = other.from;
size = other.size;
explain = other.explain;
@ -180,19 +184,21 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
}
InnerHitBuilder(InnerHitBuilder other, String nestedPath, QueryBuilder query) {
InnerHitBuilder(InnerHitBuilder other, String nestedPath, QueryBuilder query, boolean ignoreUnmapped) {
this(other);
this.query = query;
this.nestedPath = nestedPath;
this.ignoreUnmapped = ignoreUnmapped;
if (name == null) {
this.name = nestedPath;
}
}
InnerHitBuilder(InnerHitBuilder other, QueryBuilder query, String parentChildType) {
InnerHitBuilder(InnerHitBuilder other, QueryBuilder query, String parentChildType, boolean ignoreUnmapped) {
this(other);
this.query = query;
this.parentChildType = parentChildType;
this.ignoreUnmapped = ignoreUnmapped;
if (name == null) {
this.name = parentChildType;
}
@ -205,6 +211,9 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
name = in.readOptionalString();
nestedPath = in.readOptionalString();
parentChildType = in.readOptionalString();
if (in.getVersion().onOrAfter(Version.V_5_2_0_UNRELEASED)) {
ignoreUnmapped = in.readBoolean();
}
from = in.readVInt();
size = in.readVInt();
explain = in.readBoolean();
@ -243,6 +252,9 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
out.writeOptionalString(name);
out.writeOptionalString(nestedPath);
out.writeOptionalString(parentChildType);
if (out.getVersion().onOrAfter(Version.V_5_2_0_UNRELEASED)) {
out.writeBoolean(ignoreUnmapped);
}
out.writeVInt(from);
out.writeVInt(size);
out.writeBoolean(explain);
@ -289,6 +301,13 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
return this;
}
/**
* Whether to include inner hits in the search response hits if required mappings is missing
*/
public boolean isIgnoreUnmapped() {
return ignoreUnmapped;
}
public int getFrom() {
return from;
}
@ -523,6 +542,14 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
QueryShardContext queryShardContext = parentSearchContext.getQueryShardContext();
if (nestedPath != null) {
ObjectMapper nestedObjectMapper = queryShardContext.getObjectMapper(nestedPath);
if (nestedObjectMapper == null) {
if (ignoreUnmapped == false) {
throw new IllegalStateException("[" + query.getName() + "] no mapping found for type [" + nestedPath + "]");
} else {
return null;
}
}
ObjectMapper parentObjectMapper = queryShardContext.nestedScope().nextLevel(nestedObjectMapper);
InnerHitsContext.NestedInnerHits nestedInnerHits = new InnerHitsContext.NestedInnerHits(
name, parentSearchContext, parentObjectMapper, nestedObjectMapper
@ -535,7 +562,15 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
innerHitsContext.addInnerHitDefinition(nestedInnerHits);
return nestedInnerHits;
} else if (parentChildType != null) {
DocumentMapper documentMapper = queryShardContext.getMapperService().documentMapper(parentChildType);
DocumentMapper documentMapper = queryShardContext.documentMapper(parentChildType);
if (documentMapper == null) {
if (ignoreUnmapped == false) {
throw new IllegalStateException("[" + query.getName() + "] no mapping found for type [" + parentChildType + "]");
} else {
return null;
}
}
InnerHitsContext.ParentChildInnerHits parentChildInnerHits = new InnerHitsContext.ParentChildInnerHits(
name, parentSearchContext, queryShardContext.getMapperService(), documentMapper
);
@ -556,7 +591,9 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
InnerHitsContext.BaseInnerHits childInnerHit = entry.getValue().build(
parentSearchContext, new InnerHitsContext()
);
childInnerHits.put(entry.getKey(), childInnerHit);
if (childInnerHit != null) {
childInnerHits.put(entry.getKey(), childInnerHit);
}
}
innerHits.setChildInnerHits(childInnerHits);
}
@ -617,6 +654,7 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
if (name != null) {
builder.field(NAME_FIELD.getPreferredName(), name);
}
builder.field(IGNORE_UNMAPPED.getPreferredName(), ignoreUnmapped);
builder.field(SearchSourceBuilder.FROM_FIELD.getPreferredName(), from);
builder.field(SearchSourceBuilder.SIZE_FIELD.getPreferredName(), size);
builder.field(SearchSourceBuilder.VERSION_FIELD.getPreferredName(), version);
@ -672,6 +710,7 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
return Objects.equals(name, that.name) &&
Objects.equals(nestedPath, that.nestedPath) &&
Objects.equals(parentChildType, that.parentChildType) &&
Objects.equals(ignoreUnmapped, that.ignoreUnmapped) &&
Objects.equals(from, that.from) &&
Objects.equals(size, that.size) &&
Objects.equals(explain, that.explain) &&
@ -689,8 +728,8 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl
@Override
public int hashCode() {
return Objects.hash(name, nestedPath, parentChildType, from, size, explain, version, trackScores, storedFieldsContext,
docValueFields, scriptFields, fetchSourceContext, sorts, highlightBuilder, query, childInnerHits);
return Objects.hash(name, nestedPath, parentChildType, ignoreUnmapped, from, size, explain, version, trackScores,
storedFieldsContext, docValueFields, scriptFields, fetchSourceContext, sorts, highlightBuilder, query, childInnerHits);
}
public static InnerHitBuilder fromXContent(QueryParseContext context) throws IOException {

View File

@ -103,8 +103,8 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
return innerHitBuilder;
}
public NestedQueryBuilder innerHit(InnerHitBuilder innerHit) {
this.innerHitBuilder = new InnerHitBuilder(innerHit, path, query);
public NestedQueryBuilder innerHit(InnerHitBuilder innerHit, boolean ignoreUnmapped) {
this.innerHitBuilder = new InnerHitBuilder(innerHit, path, query, ignoreUnmapped);
return this;
}
@ -194,7 +194,7 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
.queryName(queryName)
.boost(boost);
if (innerHitBuilder != null) {
queryBuilder.innerHit(innerHitBuilder);
queryBuilder.innerHit(innerHitBuilder, ignoreUnmapped);
}
return queryBuilder;
}

View File

@ -41,6 +41,7 @@ import org.elasticsearch.index.cache.bitset.BitsetFilterCache;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.IndexFieldDataService;
import org.elasticsearch.index.mapper.ContentPath;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.Mapper;
import org.elasticsearch.index.mapper.MapperService;
@ -207,6 +208,14 @@ public class QueryShardContext extends QueryRewriteContext {
return mapperService.getObjectMapper(name);
}
/**
* Returns s {@link DocumentMapper} instance for the given type.
* Delegates to {@link MapperService#documentMapper(String)}
*/
public DocumentMapper documentMapper(String type) {
return mapperService.documentMapper(type);
}
/**
* Gets the search analyzer for the given field, or the default if there is none present for the field
* TODO: remove this by moving defaults into mappers themselves

View File

@ -104,13 +104,13 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
HasChildQueryBuilder hqb = new HasChildQueryBuilder(CHILD_TYPE, innerQueryBuilder,
RandomPicks.randomFrom(random(), ScoreMode.values()));
hqb.minMaxChildren(min, max);
hqb.ignoreUnmapped(randomBoolean());
if (randomBoolean()) {
hqb.innerHit(new InnerHitBuilder()
.setName(randomAsciiOfLengthBetween(1, 10))
.setSize(randomIntBetween(0, 100))
.addSort(new FieldSortBuilder(STRING_FIELD_NAME_2).order(SortOrder.ASC)));
.addSort(new FieldSortBuilder(STRING_FIELD_NAME_2).order(SortOrder.ASC)), hqb.ignoreUnmapped());
}
hqb.ignoreUnmapped(randomBoolean());
return hqb;
}
@ -189,6 +189,7 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
" \"_name\" : \"WNzYMJKRwePuRBh\",\n" +
" \"inner_hits\" : {\n" +
" \"name\" : \"inner_hits_name\",\n" +
" \"ignore_unmapped\" : false,\n" +
" \"from\" : 0,\n" +
" \"size\" : 100,\n" +
" \"version\" : false,\n" +
@ -211,7 +212,7 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
assertEquals(query, queryBuilder.childType(), "child");
assertEquals(query, queryBuilder.scoreMode(), ScoreMode.Avg);
assertNotNull(query, queryBuilder.innerHit());
InnerHitBuilder expected = new InnerHitBuilder(new InnerHitBuilder(), queryBuilder.query(), "child")
InnerHitBuilder expected = new InnerHitBuilder(new InnerHitBuilder(), queryBuilder.query(), "child", false)
.setName("inner_hits_name")
.setSize(100)
.addSort(new FieldSortBuilder("mapped_string").order(SortOrder.ASC));

View File

@ -85,13 +85,13 @@ public class HasParentQueryBuilderTests extends AbstractQueryTestCase<HasParentQ
innerQueryBuilder = new WrapperQueryBuilder(innerQueryBuilder.toString());
}
HasParentQueryBuilder hqb = new HasParentQueryBuilder(PARENT_TYPE, innerQueryBuilder, randomBoolean());
hqb.ignoreUnmapped(randomBoolean());
if (randomBoolean()) {
hqb.innerHit(new InnerHitBuilder()
.setName(randomAsciiOfLengthBetween(1, 10))
.setSize(randomIntBetween(0, 100))
.addSort(new FieldSortBuilder(STRING_FIELD_NAME_2).order(SortOrder.ASC)));
.addSort(new FieldSortBuilder(STRING_FIELD_NAME_2).order(SortOrder.ASC)), hqb.ignoreUnmapped());
}
hqb.ignoreUnmapped(randomBoolean());
return hqb;
}

View File

@ -34,7 +34,9 @@ import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.SearchModule;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.InnerHitsContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilderTests;
import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
@ -57,6 +59,8 @@ import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.sameInstance;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class InnerHitBuilderTests extends ESTestCase {
@ -120,7 +124,7 @@ public class InnerHitBuilderTests extends ESTestCase {
public void testInlineLeafInnerHitsNestedQuery() throws Exception {
InnerHitBuilder leafInnerHits = randomInnerHits();
NestedQueryBuilder nestedQueryBuilder = new NestedQueryBuilder("path", new MatchAllQueryBuilder(), ScoreMode.None);
nestedQueryBuilder.innerHit(leafInnerHits);
nestedQueryBuilder.innerHit(leafInnerHits, false);
Map<String, InnerHitBuilder> innerHitBuilders = new HashMap<>();
nestedQueryBuilder.extractInnerHitBuilders(innerHitBuilders);
assertThat(innerHitBuilders.get(leafInnerHits.getName()), notNullValue());
@ -129,7 +133,7 @@ public class InnerHitBuilderTests extends ESTestCase {
public void testInlineLeafInnerHitsHasChildQuery() throws Exception {
InnerHitBuilder leafInnerHits = randomInnerHits();
HasChildQueryBuilder hasChildQueryBuilder = new HasChildQueryBuilder("type", new MatchAllQueryBuilder(), ScoreMode.None)
.innerHit(leafInnerHits);
.innerHit(leafInnerHits, false);
Map<String, InnerHitBuilder> innerHitBuilders = new HashMap<>();
hasChildQueryBuilder.extractInnerHitBuilders(innerHitBuilders);
assertThat(innerHitBuilders.get(leafInnerHits.getName()), notNullValue());
@ -138,7 +142,7 @@ public class InnerHitBuilderTests extends ESTestCase {
public void testInlineLeafInnerHitsHasParentQuery() throws Exception {
InnerHitBuilder leafInnerHits = randomInnerHits();
HasParentQueryBuilder hasParentQueryBuilder = new HasParentQueryBuilder("type", new MatchAllQueryBuilder(), false)
.innerHit(leafInnerHits);
.innerHit(leafInnerHits, false);
Map<String, InnerHitBuilder> innerHitBuilders = new HashMap<>();
hasParentQueryBuilder.extractInnerHitBuilders(innerHitBuilders);
assertThat(innerHitBuilders.get(leafInnerHits.getName()), notNullValue());
@ -147,7 +151,7 @@ public class InnerHitBuilderTests extends ESTestCase {
public void testInlineLeafInnerHitsNestedQueryViaBoolQuery() {
InnerHitBuilder leafInnerHits = randomInnerHits();
NestedQueryBuilder nestedQueryBuilder = new NestedQueryBuilder("path", new MatchAllQueryBuilder(), ScoreMode.None)
.innerHit(leafInnerHits);
.innerHit(leafInnerHits, false);
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder().should(nestedQueryBuilder);
Map<String, InnerHitBuilder> innerHitBuilders = new HashMap<>();
boolQueryBuilder.extractInnerHitBuilders(innerHitBuilders);
@ -157,7 +161,7 @@ public class InnerHitBuilderTests extends ESTestCase {
public void testInlineLeafInnerHitsNestedQueryViaConstantScoreQuery() {
InnerHitBuilder leafInnerHits = randomInnerHits();
NestedQueryBuilder nestedQueryBuilder = new NestedQueryBuilder("path", new MatchAllQueryBuilder(), ScoreMode.None)
.innerHit(leafInnerHits);
.innerHit(leafInnerHits, false);
ConstantScoreQueryBuilder constantScoreQueryBuilder = new ConstantScoreQueryBuilder(nestedQueryBuilder);
Map<String, InnerHitBuilder> innerHitBuilders = new HashMap<>();
constantScoreQueryBuilder.extractInnerHitBuilders(innerHitBuilders);
@ -167,10 +171,10 @@ public class InnerHitBuilderTests extends ESTestCase {
public void testInlineLeafInnerHitsNestedQueryViaBoostingQuery() {
InnerHitBuilder leafInnerHits1 = randomInnerHits();
NestedQueryBuilder nestedQueryBuilder1 = new NestedQueryBuilder("path", new MatchAllQueryBuilder(), ScoreMode.None)
.innerHit(leafInnerHits1);
.innerHit(leafInnerHits1, false);
InnerHitBuilder leafInnerHits2 = randomInnerHits();
NestedQueryBuilder nestedQueryBuilder2 = new NestedQueryBuilder("path", new MatchAllQueryBuilder(), ScoreMode.None)
.innerHit(leafInnerHits2);
.innerHit(leafInnerHits2, false);
BoostingQueryBuilder constantScoreQueryBuilder = new BoostingQueryBuilder(nestedQueryBuilder1, nestedQueryBuilder2);
Map<String, InnerHitBuilder> innerHitBuilders = new HashMap<>();
constantScoreQueryBuilder.extractInnerHitBuilders(innerHitBuilders);
@ -181,13 +185,68 @@ public class InnerHitBuilderTests extends ESTestCase {
public void testInlineLeafInnerHitsNestedQueryViaFunctionScoreQuery() {
InnerHitBuilder leafInnerHits = randomInnerHits();
NestedQueryBuilder nestedQueryBuilder = new NestedQueryBuilder("path", new MatchAllQueryBuilder(), ScoreMode.None)
.innerHit(leafInnerHits);
.innerHit(leafInnerHits, false);
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(nestedQueryBuilder);
Map<String, InnerHitBuilder> innerHitBuilders = new HashMap<>();
((AbstractQueryBuilder<?>) functionScoreQueryBuilder).extractInnerHitBuilders(innerHitBuilders);
assertThat(innerHitBuilders.get(leafInnerHits.getName()), notNullValue());
}
public void testBuild_ingoreUnmappedNestQuery() throws Exception {
QueryShardContext queryShardContext = mock(QueryShardContext.class);
when(queryShardContext.getObjectMapper("path")).thenReturn(null);
SearchContext searchContext = mock(SearchContext.class);
when(searchContext.getQueryShardContext()).thenReturn(queryShardContext);
InnerHitBuilder leafInnerHits = randomInnerHits();
NestedQueryBuilder query1 = new NestedQueryBuilder("path", new MatchAllQueryBuilder(), ScoreMode.None);
query1.innerHit(leafInnerHits, false);
expectThrows(IllegalStateException.class, () -> query1.innerHit().build(searchContext, new InnerHitsContext()));
NestedQueryBuilder query2 = new NestedQueryBuilder("path", new MatchAllQueryBuilder(), ScoreMode.None);
query2.innerHit(leafInnerHits, true);
InnerHitsContext innerHitsContext = new InnerHitsContext();
query2.innerHit().build(searchContext, innerHitsContext);
assertThat(innerHitsContext.getInnerHits().size(), equalTo(0));
}
public void testBuild_ignoreUnmappedHasChildQuery() throws Exception {
QueryShardContext queryShardContext = mock(QueryShardContext.class);
when(queryShardContext.documentMapper("type")).thenReturn(null);
SearchContext searchContext = mock(SearchContext.class);
when(searchContext.getQueryShardContext()).thenReturn(queryShardContext);
InnerHitBuilder leafInnerHits = randomInnerHits();
HasChildQueryBuilder query1 = new HasChildQueryBuilder("type", new MatchAllQueryBuilder(), ScoreMode.None)
.innerHit(leafInnerHits, false);
expectThrows(IllegalStateException.class, () -> query1.innerHit().build(searchContext, new InnerHitsContext()));
HasChildQueryBuilder query2 = new HasChildQueryBuilder("type", new MatchAllQueryBuilder(), ScoreMode.None)
.innerHit(leafInnerHits, true);
InnerHitsContext innerHitsContext = new InnerHitsContext();
query2.innerHit().build(searchContext, innerHitsContext);
assertThat(innerHitsContext.getInnerHits().size(), equalTo(0));
}
public void testBuild_ingoreUnmappedHasParentQuery() throws Exception {
QueryShardContext queryShardContext = mock(QueryShardContext.class);
when(queryShardContext.documentMapper("type")).thenReturn(null);
SearchContext searchContext = mock(SearchContext.class);
when(searchContext.getQueryShardContext()).thenReturn(queryShardContext);
InnerHitBuilder leafInnerHits = randomInnerHits();
HasParentQueryBuilder query1 = new HasParentQueryBuilder("type", new MatchAllQueryBuilder(), false)
.innerHit(leafInnerHits, false);
expectThrows(IllegalStateException.class, () -> query1.innerHit().build(searchContext, new InnerHitsContext()));
HasParentQueryBuilder query2 = new HasParentQueryBuilder("type", new MatchAllQueryBuilder(), false)
.innerHit(leafInnerHits, true);
InnerHitsContext innerHitsContext = new InnerHitsContext();
query2.innerHit().build(searchContext, innerHitsContext);
assertThat(innerHitsContext.getInnerHits().size(), equalTo(0));
}
public static InnerHitBuilder randomInnerHits() {
return randomInnerHits(true, true);
}
@ -236,9 +295,9 @@ public class InnerHitBuilderTests extends ESTestCase {
if (includeQueryTypeOrPath) {
QueryBuilder query = new MatchQueryBuilder(randomAsciiOfLengthBetween(1, 16), randomAsciiOfLengthBetween(1, 16));
if (randomBoolean()) {
return new InnerHitBuilder(innerHits, randomAsciiOfLength(8), query);
return new InnerHitBuilder(innerHits, randomAsciiOfLength(8), query, randomBoolean());
} else {
return new InnerHitBuilder(innerHits, query, randomAsciiOfLength(8));
return new InnerHitBuilder(innerHits, query, randomAsciiOfLength(8), randomBoolean());
}
} else {
return innerHits;
@ -248,8 +307,8 @@ public class InnerHitBuilderTests extends ESTestCase {
public void testCopyConstructor() throws Exception {
InnerHitBuilder original = randomInnerHits();
InnerHitBuilder copy = original.getNestedPath() != null ?
new InnerHitBuilder(original, original.getNestedPath(), original.getQuery()) :
new InnerHitBuilder(original, original.getQuery(), original.getParentChildType());
new InnerHitBuilder(original, original.getNestedPath(), original.getQuery(), original.isIgnoreUnmapped()) :
new InnerHitBuilder(original, original.getQuery(), original.getParentChildType(), original.isIgnoreUnmapped());
assertThat(copy, equalTo(original));
copy = mutate(copy);
assertThat(copy, not(equalTo(original)));

View File

@ -73,13 +73,13 @@ public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBu
}
NestedQueryBuilder nqb = new NestedQueryBuilder("nested1", innerQueryBuilder,
RandomPicks.randomFrom(random(), ScoreMode.values()));
nqb.ignoreUnmapped(randomBoolean());
if (randomBoolean()) {
nqb.innerHit(new InnerHitBuilder()
.setName(randomAsciiOfLengthBetween(1, 10))
.setSize(randomIntBetween(0, 100))
.addSort(new FieldSortBuilder(INT_FIELD_NAME).order(SortOrder.ASC)));
.addSort(new FieldSortBuilder(INT_FIELD_NAME).order(SortOrder.ASC)), nqb.ignoreUnmapped());
}
nqb.ignoreUnmapped(randomBoolean());
return nqb;
}

View File

@ -94,7 +94,6 @@ import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
@ -822,7 +821,8 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
SearchResponse searchResponse = client().prepareSearch("test").setQuery(
hasChildQuery("child", matchQuery("c_field", "foo"), ScoreMode.None)
.innerHit(new InnerHitBuilder().setHighlightBuilder(
new HighlightBuilder().field(new Field("c_field").highlightQuery(QueryBuilders.matchQuery("c_field", "bar"))))))
new HighlightBuilder().field(new Field("c_field")
.highlightQuery(QueryBuilders.matchQuery("c_field", "bar")))), false))
.get();
assertNoFailures(searchResponse);
assertThat(searchResponse.getHits().totalHits(), equalTo(1L));

View File

@ -123,7 +123,7 @@ public class InnerHitsIT extends ESIntegTestCase {
SearchResponse response = client().prepareSearch("articles")
.setQuery(nestedQuery("comments", matchQuery("comments.message", "fox"), ScoreMode.Avg)
.innerHit(new InnerHitBuilder().setName("comment"))
.innerHit(new InnerHitBuilder().setName("comment"), false)
).get();
assertNoFailures(response);
assertHitCount(response, 1);
@ -141,7 +141,7 @@ public class InnerHitsIT extends ESIntegTestCase {
response = client().prepareSearch("articles")
.setQuery(nestedQuery("comments", matchQuery("comments.message", "elephant"), ScoreMode.Avg)
.innerHit(new InnerHitBuilder().setName("comment"))
.innerHit(new InnerHitBuilder().setName("comment"), false)
).get();
assertNoFailures(response);
assertHitCount(response, 1);
@ -168,8 +168,8 @@ public class InnerHitsIT extends ESIntegTestCase {
.addDocValueField("comments.message")
.addScriptField("script",
new Script(ScriptType.INLINE, MockScriptEngine.NAME, "5", Collections.emptyMap()))
.setSize(1)
)).get();
.setSize(1),
false)).get();
assertNoFailures(response);
innerHits = response.getHits().getAt(0).getInnerHits().get("comments");
assertThat(innerHits.getTotalHits(), equalTo(2L));
@ -207,9 +207,9 @@ public class InnerHitsIT extends ESIntegTestCase {
int size = randomIntBetween(0, numDocs);
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
boolQuery.should(nestedQuery("field1", matchAllQuery(), ScoreMode.Avg).innerHit(new InnerHitBuilder().setName("a").setSize(size)
.addSort(new FieldSortBuilder("_doc").order(SortOrder.DESC))));
.addSort(new FieldSortBuilder("_doc").order(SortOrder.DESC)), false));
boolQuery.should(nestedQuery("field2", matchAllQuery(), ScoreMode.Avg).innerHit(new InnerHitBuilder().setName("b")
.addSort(new FieldSortBuilder("_doc").order(SortOrder.DESC)).setSize(size)));
.addSort(new FieldSortBuilder("_doc").order(SortOrder.DESC)).setSize(size), false));
SearchResponse searchResponse = client().prepareSearch("idx")
.setQuery(boolQuery)
.setSize(numDocs)
@ -260,7 +260,8 @@ public class InnerHitsIT extends ESIntegTestCase {
indexRandom(true, requests);
SearchResponse response = client().prepareSearch("articles")
.setQuery(hasChildQuery("comment", matchQuery("message", "fox"), ScoreMode.None).innerHit(new InnerHitBuilder()))
.setQuery(hasChildQuery("comment", matchQuery("message", "fox"), ScoreMode.None)
.innerHit(new InnerHitBuilder(), false))
.get();
assertNoFailures(response);
assertHitCount(response, 1);
@ -277,7 +278,8 @@ public class InnerHitsIT extends ESIntegTestCase {
assertThat(innerHits.getAt(1).type(), equalTo("comment"));
response = client().prepareSearch("articles")
.setQuery(hasChildQuery("comment", matchQuery("message", "elephant"), ScoreMode.None).innerHit(new InnerHitBuilder()))
.setQuery(hasChildQuery("comment", matchQuery("message", "elephant"), ScoreMode.None)
.innerHit(new InnerHitBuilder(), false))
.get();
assertNoFailures(response);
assertHitCount(response, 1);
@ -302,8 +304,8 @@ public class InnerHitsIT extends ESIntegTestCase {
.setHighlightBuilder(new HighlightBuilder().field("message"))
.setExplain(true).setSize(1)
.addScriptField("script", new Script(ScriptType.INLINE, MockScriptEngine.NAME, "5",
Collections.emptyMap()))
)
Collections.emptyMap())),
false)
).get();
assertNoFailures(response);
innerHits = response.getHits().getAt(0).getInnerHits().get("comment");
@ -349,9 +351,11 @@ public class InnerHitsIT extends ESIntegTestCase {
int size = randomIntBetween(0, numDocs);
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
boolQuery.should(constantScoreQuery(hasChildQuery("child1", matchAllQuery(), ScoreMode.None)
.innerHit(new InnerHitBuilder().setName("a").addSort(new FieldSortBuilder("_uid").order(SortOrder.ASC)).setSize(size))));
.innerHit(new InnerHitBuilder().setName("a")
.addSort(new FieldSortBuilder("_uid").order(SortOrder.ASC)).setSize(size), false)));
boolQuery.should(constantScoreQuery(hasChildQuery("child2", matchAllQuery(), ScoreMode.None)
.innerHit(new InnerHitBuilder().setName("b").addSort(new FieldSortBuilder("_uid").order(SortOrder.ASC)).setSize(size))));
.innerHit(new InnerHitBuilder().setName("b")
.addSort(new FieldSortBuilder("_uid").order(SortOrder.ASC)).setSize(size), false)));
SearchResponse searchResponse = client().prepareSearch("idx")
.setSize(numDocs)
.setTypes("parent")
@ -417,7 +421,7 @@ public class InnerHitsIT extends ESIntegTestCase {
.setQuery(
boolQuery()
.must(matchQuery("body", "fail2ban"))
.must(hasParentQuery("question", matchAllQuery(), false).innerHit(new InnerHitBuilder()))
.must(hasParentQuery("question", matchAllQuery(), false).innerHit(new InnerHitBuilder(), false))
).get();
assertNoFailures(response);
assertHitCount(response, 2);
@ -455,8 +459,8 @@ public class InnerHitsIT extends ESIntegTestCase {
SearchResponse response = client().prepareSearch("articles")
.setQuery(hasChildQuery("comment",
hasChildQuery("remark", matchQuery("message", "good"), ScoreMode.None).innerHit(new InnerHitBuilder()),
ScoreMode.None).innerHit(new InnerHitBuilder()))
hasChildQuery("remark", matchQuery("message", "good"), ScoreMode.None).innerHit(new InnerHitBuilder(), false),
ScoreMode.None).innerHit(new InnerHitBuilder(), false))
.get();
assertNoFailures(response);
@ -476,8 +480,8 @@ public class InnerHitsIT extends ESIntegTestCase {
response = client().prepareSearch("articles")
.setQuery(hasChildQuery("comment",
hasChildQuery("remark", matchQuery("message", "bad"), ScoreMode.None).innerHit(new InnerHitBuilder()),
ScoreMode.None).innerHit(new InnerHitBuilder()))
hasChildQuery("remark", matchQuery("message", "bad"), ScoreMode.None).innerHit(new InnerHitBuilder(), false),
ScoreMode.None).innerHit(new InnerHitBuilder(), false))
.get();
assertNoFailures(response);
@ -543,8 +547,8 @@ public class InnerHitsIT extends ESIntegTestCase {
.setQuery(
nestedQuery("comments",
nestedQuery("comments.remarks", matchQuery("comments.remarks.message", "good"), ScoreMode.Avg)
.innerHit(new InnerHitBuilder().setName("remark")),
ScoreMode.Avg).innerHit(new InnerHitBuilder())
.innerHit(new InnerHitBuilder().setName("remark"), false),
ScoreMode.Avg).innerHit(new InnerHitBuilder(), false)
).get();
assertNoFailures(response);
assertHitCount(response, 1);
@ -568,7 +572,7 @@ public class InnerHitsIT extends ESIntegTestCase {
// Directly refer to the second level:
response = client().prepareSearch("articles")
.setQuery(nestedQuery("comments.remarks", matchQuery("comments.remarks.message", "bad"), ScoreMode.Avg)
.innerHit(new InnerHitBuilder())).get();
.innerHit(new InnerHitBuilder(), false)).get();
assertNoFailures(response);
assertHitCount(response, 1);
assertSearchHit(response, 1, hasId("2"));
@ -586,8 +590,8 @@ public class InnerHitsIT extends ESIntegTestCase {
.setQuery(
nestedQuery("comments",
nestedQuery("comments.remarks", matchQuery("comments.remarks.message", "bad"), ScoreMode.Avg)
.innerHit(new InnerHitBuilder().setName("remark")),
ScoreMode.Avg).innerHit(new InnerHitBuilder())
.innerHit(new InnerHitBuilder().setName("remark"), false),
ScoreMode.Avg).innerHit(new InnerHitBuilder(), false)
).get();
assertNoFailures(response);
assertHitCount(response, 1);
@ -621,7 +625,8 @@ public class InnerHitsIT extends ESIntegTestCase {
indexRandom(true, requests);
SearchResponse response = client().prepareSearch("articles")
.setQuery(nestedQuery("comments", matchQuery("comments.message", "fox"), ScoreMode.Avg).innerHit(new InnerHitBuilder()))
.setQuery(nestedQuery("comments", matchQuery("comments.message", "fox"), ScoreMode.Avg)
.innerHit(new InnerHitBuilder(), false))
.get();
assertNoFailures(response);
assertHitCount(response, 1);
@ -663,7 +668,7 @@ public class InnerHitsIT extends ESIntegTestCase {
SearchResponse response = client().prepareSearch("articles")
.setQuery(nestedQuery("comments.messages", matchQuery("comments.messages.message", "fox"), ScoreMode.Avg)
.innerHit(new InnerHitBuilder())).get();
.innerHit(new InnerHitBuilder(), false)).get();
assertNoFailures(response);
assertHitCount(response, 1);
SearchHit hit = response.getHits().getAt(0);
@ -677,7 +682,7 @@ public class InnerHitsIT extends ESIntegTestCase {
response = client().prepareSearch("articles")
.setQuery(nestedQuery("comments.messages", matchQuery("comments.messages.message", "bear"), ScoreMode.Avg)
.innerHit(new InnerHitBuilder())).get();
.innerHit(new InnerHitBuilder(), false)).get();
assertNoFailures(response);
assertHitCount(response, 1);
hit = response.getHits().getAt(0);
@ -698,7 +703,7 @@ public class InnerHitsIT extends ESIntegTestCase {
indexRandom(true, requests);
response = client().prepareSearch("articles")
.setQuery(nestedQuery("comments.messages", matchQuery("comments.messages.message", "fox"), ScoreMode.Avg)
.innerHit(new InnerHitBuilder())).get();
.innerHit(new InnerHitBuilder(), false)).get();
assertNoFailures(response);
assertHitCount(response, 1);
hit = response.getHits().getAt(0);;
@ -739,15 +744,16 @@ public class InnerHitsIT extends ESIntegTestCase {
.setTypes("duke")
.setQuery(boolQuery()
.filter(hasParentQuery("prince",
hasParentQuery("king", matchAllQuery(), false).innerHit(new InnerHitBuilder().setName("kings")),
false).innerHit(new InnerHitBuilder().setName("princes"))
hasParentQuery("king", matchAllQuery(), false).innerHit(new InnerHitBuilder().setName("kings"), false),
false).innerHit(new InnerHitBuilder().setName("princes"), false)
)
.filter(hasChildQuery("earl",
hasChildQuery("baron", matchAllQuery(), ScoreMode.None).innerHit(new InnerHitBuilder().setName("barons")),
hasChildQuery("baron", matchAllQuery(), ScoreMode.None)
.innerHit(new InnerHitBuilder().setName("barons"), false),
ScoreMode.None).innerHit(new InnerHitBuilder()
.addSort(SortBuilders.fieldSort("_uid").order(SortOrder.ASC))
.setName("earls")
.setSize(4))
.setSize(4), false)
)
)
.get();
@ -860,7 +866,7 @@ public class InnerHitsIT extends ESIntegTestCase {
.should(termQuery("nested1.n_field1", "n_value1_3").queryName("test2"))
.should(termQuery("nested1.n_field2", "n_value2_2").queryName("test3"));
query = nestedQuery("nested1", query, ScoreMode.Avg).innerHit(
new InnerHitBuilder().addSort(new FieldSortBuilder("nested1.n_field1").order(SortOrder.ASC)));
new InnerHitBuilder().addSort(new FieldSortBuilder("nested1.n_field1").order(SortOrder.ASC)), false);
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(query)
.setSize(numDocs)
@ -902,7 +908,7 @@ public class InnerHitsIT extends ESIntegTestCase {
SearchResponse response = client().prepareSearch("index")
.setQuery(hasChildQuery("child", matchQuery("field", "value1").queryName("_name1"), ScoreMode.None)
.innerHit(new InnerHitBuilder()))
.innerHit(new InnerHitBuilder(), false))
.addSort("_uid", SortOrder.ASC)
.get();
assertHitCount(response, 2);
@ -917,7 +923,7 @@ public class InnerHitsIT extends ESIntegTestCase {
assertThat(response.getHits().getAt(1).getInnerHits().get("child").getAt(0).getMatchedQueries()[0], equalTo("_name1"));
QueryBuilder query = hasChildQuery("child", matchQuery("field", "value2").queryName("_name2"), ScoreMode.None)
.innerHit(new InnerHitBuilder());
.innerHit(new InnerHitBuilder(), false);
response = client().prepareSearch("index")
.setQuery(query)
.addSort("_uid", SortOrder.ASC)
@ -937,7 +943,7 @@ public class InnerHitsIT extends ESIntegTestCase {
indexRandom(true, requests);
QueryBuilder query = hasChildQuery("child", matchQuery("field", "value1"), ScoreMode.None)
.innerHit(new InnerHitBuilder().setSize(ArrayUtil.MAX_ARRAY_LENGTH - 1));
.innerHit(new InnerHitBuilder().setSize(ArrayUtil.MAX_ARRAY_LENGTH - 1), false);
SearchResponse response = client().prepareSearch("index1")
.setQuery(query)
.addSort("_uid", SortOrder.ASC)
@ -957,7 +963,7 @@ public class InnerHitsIT extends ESIntegTestCase {
.get();
query = nestedQuery("nested", matchQuery("nested.field", "value1"), ScoreMode.Avg)
.innerHit(new InnerHitBuilder().setSize(ArrayUtil.MAX_ARRAY_LENGTH - 1));
.innerHit(new InnerHitBuilder().setSize(ArrayUtil.MAX_ARRAY_LENGTH - 1), false);
response = client().prepareSearch("index2")
.setQuery(query)
.addSort("_uid", SortOrder.ASC)
@ -983,7 +989,7 @@ public class InnerHitsIT extends ESIntegTestCase {
SearchResponse response = client().prepareSearch()
.setQuery(nestedQuery("comments", matchQuery("comments.message", "fox"), ScoreMode.None)
.innerHit(new InnerHitBuilder().setFetchSourceContext(new FetchSourceContext(true,
new String[]{"comments.message"}, null))))
new String[]{"comments.message"}, null)), false))
.get();
assertNoFailures(response);
assertHitCount(response, 1);
@ -1004,7 +1010,7 @@ public class InnerHitsIT extends ESIntegTestCase {
SearchResponse response = client().prepareSearch("test")
.setQuery(boolQuery().must(matchQuery("key", "value"))
.should(hasChildQuery("child_type", nestedQuery("nested_type", matchAllQuery(), ScoreMode.None)
.innerHit(new InnerHitBuilder()), ScoreMode.None).innerHit(new InnerHitBuilder())))
.innerHit(new InnerHitBuilder(), false), ScoreMode.None).innerHit(new InnerHitBuilder(), false)))
.get();
assertHitCount(response, 1);
SearchHit hit = response.getHits().getAt(0);
@ -1012,4 +1018,40 @@ public class InnerHitsIT extends ESIntegTestCase {
assertThat(hit.getInnerHits().get("child_type").getAt(0).getInnerHits().get("nested_type").getAt(0).field("_parent"), nullValue());
}
public void testInnerHitsWithIgnoreUnmapped() throws Exception {
assertAcked(prepareCreate("index1")
.addMapping("parent_type", "nested_type", "type=nested")
.addMapping("child_type", "_parent", "type=parent_type")
);
createIndex("index2");
client().prepareIndex("index1", "parent_type", "1").setSource("nested_type", Collections.singletonMap("key", "value")).get();
client().prepareIndex("index1", "child_type", "2").setParent("1").setSource("{}").get();
client().prepareIndex("index2", "type", "3").setSource("key", "value").get();
refresh();
SearchResponse response = client().prepareSearch("index1", "index2")
.setQuery(boolQuery()
.should(nestedQuery("nested_type", matchAllQuery(), ScoreMode.None).ignoreUnmapped(true)
.innerHit(new InnerHitBuilder(), true))
.should(termQuery("key", "value"))
)
.addSort("_uid", SortOrder.ASC)
.get();
assertNoFailures(response);
assertHitCount(response, 2);
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
response = client().prepareSearch("index1", "index2")
.setQuery(boolQuery()
.should(hasChildQuery("child_type", matchAllQuery(), ScoreMode.None).ignoreUnmapped(true)
.innerHit(new InnerHitBuilder(), true))
.should(termQuery("key", "value"))
)
.addSort("_uid", SortOrder.ASC)
.get();
assertNoFailures(response);
assertHitCount(response, 2);
assertThat(response.getHits().getAt(0).getId(), equalTo("1"));
}
}