Adds ignore_unmapped option to nested and P/C queries
The change adds a new option to the `nested`, `has_parent`, `has_children` and `parent_id` queries: `ignore_unmapped`. If this option is set to false, the `toQuery` method on the QueryBuilder will throw an exception if the type/path specified in the query is unmapped. If the option is set to true, the `toQuery` method on the QueryBuilder will return a MatchNoDocsQuery. The default value is `false`so the queries work how they do today (throwing an exception on unmapped paths/types)
This commit is contained in:
parent
acec464eb8
commit
686aff1545
|
@ -63,6 +63,11 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
* The default minimum number of children that are required to match for the parent to be considered a match.
|
||||
*/
|
||||
public static final int DEFAULT_MIN_CHILDREN = 0;
|
||||
|
||||
/**
|
||||
* The default value for ignore_unmapped.
|
||||
*/
|
||||
public static final boolean DEFAULT_IGNORE_UNMAPPED = false;
|
||||
/*
|
||||
* The default score mode that is used to combine score coming from multiple parent documents.
|
||||
*/
|
||||
|
@ -74,6 +79,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
private static final ParseField MIN_CHILDREN_FIELD = new ParseField("min_children");
|
||||
private static final ParseField SCORE_MODE_FIELD = new ParseField("score_mode");
|
||||
private static final ParseField INNER_HITS_FIELD = new ParseField("inner_hits");
|
||||
private static final ParseField IGNORE_UNMAPPED_FIELD = new ParseField("ignore_unmapped");
|
||||
|
||||
private final QueryBuilder<?> query;
|
||||
|
||||
|
@ -87,6 +93,8 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
|
||||
private InnerHitBuilder innerHitBuilder;
|
||||
|
||||
private boolean ignoreUnmapped = false;
|
||||
|
||||
|
||||
public HasChildQueryBuilder(String type, QueryBuilder<?> query, int maxChildren, int minChildren, ScoreMode scoreMode,
|
||||
InnerHitBuilder innerHitBuilder) {
|
||||
|
@ -123,6 +131,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
scoreMode = ScoreMode.values()[in.readVInt()];
|
||||
query = in.readQuery();
|
||||
innerHitBuilder = in.readOptionalWriteable(InnerHitBuilder::new);
|
||||
ignoreUnmapped = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -133,6 +142,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
out.writeVInt(scoreMode.ordinal());
|
||||
out.writeQuery(query);
|
||||
out.writeOptionalWriteable(innerHitBuilder);
|
||||
out.writeBoolean(ignoreUnmapped);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -220,6 +230,25 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
*/
|
||||
public int maxChildren() { return maxChildren; }
|
||||
|
||||
/**
|
||||
* Sets whether the query builder should ignore unmapped types (and run a
|
||||
* {@link MatchNoDocsQuery} in place of this query) or throw an exception if
|
||||
* the type is unmapped.
|
||||
*/
|
||||
public HasChildQueryBuilder ignoreUnmapped(boolean ignoreUnmapped) {
|
||||
this.ignoreUnmapped = ignoreUnmapped;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the query builder will ignore unmapped types (and run a
|
||||
* {@link MatchNoDocsQuery} in place of this query) or throw an exception if
|
||||
* the type is unmapped.
|
||||
*/
|
||||
public boolean ignoreUnmapped() {
|
||||
return ignoreUnmapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(NAME);
|
||||
|
@ -229,6 +258,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
builder.field(SCORE_MODE_FIELD.getPreferredName(), scoreModeAsString(scoreMode));
|
||||
builder.field(MIN_CHILDREN_FIELD.getPreferredName(), minChildren);
|
||||
builder.field(MAX_CHILDREN_FIELD.getPreferredName(), maxChildren);
|
||||
builder.field(IGNORE_UNMAPPED_FIELD.getPreferredName(), ignoreUnmapped);
|
||||
printBoostAndQueryName(builder);
|
||||
if (innerHitBuilder != null) {
|
||||
builder.field(INNER_HITS_FIELD.getPreferredName(), innerHitBuilder, params);
|
||||
|
@ -243,6 +273,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
ScoreMode scoreMode = HasChildQueryBuilder.DEFAULT_SCORE_MODE;
|
||||
int minChildren = HasChildQueryBuilder.DEFAULT_MIN_CHILDREN;
|
||||
int maxChildren = HasChildQueryBuilder.DEFAULT_MAX_CHILDREN;
|
||||
boolean ignoreUnmapped = DEFAULT_IGNORE_UNMAPPED;
|
||||
String queryName = null;
|
||||
InnerHitBuilder innerHitBuilder = null;
|
||||
String currentFieldName = null;
|
||||
|
@ -272,6 +303,8 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
minChildren = parser.intValue(true);
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, MAX_CHILDREN_FIELD)) {
|
||||
maxChildren = parser.intValue(true);
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, IGNORE_UNMAPPED_FIELD)) {
|
||||
ignoreUnmapped = parser.booleanValue();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.NAME_FIELD)) {
|
||||
queryName = parser.text();
|
||||
} else {
|
||||
|
@ -283,6 +316,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
scoreMode, innerHitBuilder);
|
||||
hasChildQueryBuilder.queryName(queryName);
|
||||
hasChildQueryBuilder.boost(boost);
|
||||
hasChildQueryBuilder.ignoreUnmapped(ignoreUnmapped);
|
||||
return hasChildQueryBuilder;
|
||||
}
|
||||
|
||||
|
@ -331,7 +365,11 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
}
|
||||
DocumentMapper childDocMapper = context.getMapperService().documentMapper(type);
|
||||
if (childDocMapper == null) {
|
||||
throw new QueryShardException(context, "[" + NAME + "] no mapping found for type [" + type + "]");
|
||||
if (ignoreUnmapped) {
|
||||
return new MatchNoDocsQuery();
|
||||
} else {
|
||||
throw new QueryShardException(context, "[" + NAME + "] no mapping found for type [" + type + "]");
|
||||
}
|
||||
}
|
||||
ParentFieldMapper parentFieldMapper = childDocMapper.parentFieldMapper();
|
||||
if (parentFieldMapper.active() == false) {
|
||||
|
@ -344,8 +382,8 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
String parentType = parentFieldMapper.type();
|
||||
DocumentMapper parentDocMapper = context.getMapperService().documentMapper(parentType);
|
||||
if (parentDocMapper == null) {
|
||||
throw new QueryShardException(context, "[" + NAME + "] Type [" + type + "] points to a non existent parent type ["
|
||||
+ parentType + "]");
|
||||
throw new QueryShardException(context,
|
||||
"[" + NAME + "] Type [" + type + "] points to a non existent parent type [" + parentType + "]");
|
||||
}
|
||||
|
||||
if (maxChildren > 0 && maxChildren < minChildren) {
|
||||
|
@ -464,12 +502,13 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
&& Objects.equals(scoreMode, that.scoreMode)
|
||||
&& Objects.equals(minChildren, that.minChildren)
|
||||
&& Objects.equals(maxChildren, that.maxChildren)
|
||||
&& Objects.equals(innerHitBuilder, that.innerHitBuilder);
|
||||
&& Objects.equals(innerHitBuilder, that.innerHitBuilder)
|
||||
&& Objects.equals(ignoreUnmapped, that.ignoreUnmapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doHashCode() {
|
||||
return Objects.hash(query, type, scoreMode, minChildren, maxChildren, innerHitBuilder);
|
||||
return Objects.hash(query, type, scoreMode, minChildren, maxChildren, innerHitBuilder, ignoreUnmapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.elasticsearch.index.query;
|
|||
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
|
@ -49,16 +50,23 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
|
|||
|
||||
public static final boolean DEFAULT_SCORE = false;
|
||||
|
||||
/**
|
||||
* The default value for ignore_unmapped.
|
||||
*/
|
||||
public static final boolean DEFAULT_IGNORE_UNMAPPED = false;
|
||||
|
||||
private static final ParseField QUERY_FIELD = new ParseField("query", "filter");
|
||||
private static final ParseField SCORE_MODE_FIELD = new ParseField("score_mode").withAllDeprecated("score");
|
||||
private static final ParseField TYPE_FIELD = new ParseField("parent_type", "type");
|
||||
private static final ParseField SCORE_FIELD = new ParseField("score");
|
||||
private static final ParseField INNER_HITS_FIELD = new ParseField("inner_hits");
|
||||
private static final ParseField IGNORE_UNMAPPED_FIELD = new ParseField("ignore_unmapped");
|
||||
|
||||
private final QueryBuilder<?> query;
|
||||
private final String type;
|
||||
private boolean score = DEFAULT_SCORE;
|
||||
private InnerHitBuilder innerHit;
|
||||
private boolean ignoreUnmapped = false;
|
||||
|
||||
/**
|
||||
* @param type The parent type
|
||||
|
@ -94,6 +102,7 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
|
|||
score = in.readBoolean();
|
||||
query = in.readQuery();
|
||||
innerHit = in.readOptionalWriteable(InnerHitBuilder::new);
|
||||
ignoreUnmapped = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -102,6 +111,7 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
|
|||
out.writeBoolean(score);
|
||||
out.writeQuery(query);
|
||||
out.writeOptionalWriteable(innerHit);
|
||||
out.writeBoolean(ignoreUnmapped);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,6 +160,25 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
|
|||
return innerHit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the query builder should ignore unmapped types (and run a
|
||||
* {@link MatchNoDocsQuery} in place of this query) or throw an exception if
|
||||
* the type is unmapped.
|
||||
*/
|
||||
public HasParentQueryBuilder ignoreUnmapped(boolean ignoreUnmapped) {
|
||||
this.ignoreUnmapped = ignoreUnmapped;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the query builder will ignore unmapped types (and run a
|
||||
* {@link MatchNoDocsQuery} in place of this query) or throw an exception if
|
||||
* the type is unmapped.
|
||||
*/
|
||||
public boolean ignoreUnmapped() {
|
||||
return ignoreUnmapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query doToQuery(QueryShardContext context) throws IOException {
|
||||
Query innerQuery;
|
||||
|
@ -166,8 +195,11 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
|
|||
}
|
||||
DocumentMapper parentDocMapper = context.getMapperService().documentMapper(type);
|
||||
if (parentDocMapper == null) {
|
||||
throw new QueryShardException(context, "[" + NAME + "] query configured 'parent_type' [" + type
|
||||
+ "] is not a valid type");
|
||||
if (ignoreUnmapped) {
|
||||
return new MatchNoDocsQuery();
|
||||
} else {
|
||||
throw new QueryShardException(context, "[" + NAME + "] query configured 'parent_type' [" + type + "] is not a valid type");
|
||||
}
|
||||
}
|
||||
|
||||
if (innerHit != null) {
|
||||
|
@ -220,6 +252,7 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
|
|||
query.toXContent(builder, params);
|
||||
builder.field(TYPE_FIELD.getPreferredName(), type);
|
||||
builder.field(SCORE_FIELD.getPreferredName(), score);
|
||||
builder.field(IGNORE_UNMAPPED_FIELD.getPreferredName(), ignoreUnmapped);
|
||||
printBoostAndQueryName(builder);
|
||||
if (innerHit != null) {
|
||||
builder.field(INNER_HITS_FIELD.getPreferredName(), innerHit, params);
|
||||
|
@ -234,6 +267,7 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
|
|||
boolean score = HasParentQueryBuilder.DEFAULT_SCORE;
|
||||
String queryName = null;
|
||||
InnerHitBuilder innerHits = null;
|
||||
boolean ignoreUnmapped = DEFAULT_IGNORE_UNMAPPED;
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
|
@ -264,6 +298,8 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
|
|||
}
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, SCORE_FIELD)) {
|
||||
score = parser.booleanValue();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, IGNORE_UNMAPPED_FIELD)) {
|
||||
ignoreUnmapped = parser.booleanValue();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.BOOST_FIELD)) {
|
||||
boost = parser.floatValue();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.NAME_FIELD)) {
|
||||
|
@ -273,7 +309,8 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
|
|||
}
|
||||
}
|
||||
}
|
||||
return new HasParentQueryBuilder(parentType, iqb, score, innerHits).queryName(queryName).boost(boost);
|
||||
return new HasParentQueryBuilder(parentType, iqb, score, innerHits).ignoreUnmapped(ignoreUnmapped).queryName(queryName)
|
||||
.boost(boost);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -286,12 +323,13 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
|
|||
return Objects.equals(query, that.query)
|
||||
&& Objects.equals(type, that.type)
|
||||
&& Objects.equals(score, that.score)
|
||||
&& Objects.equals(innerHit, that.innerHit);
|
||||
&& Objects.equals(innerHit, that.innerHit)
|
||||
&& Objects.equals(ignoreUnmapped, that.ignoreUnmapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doHashCode() {
|
||||
return Objects.hash(query, type, score, innerHit);
|
||||
return Objects.hash(query, type, score, innerHit, ignoreUnmapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.join.BitSetProducer;
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
|
@ -45,14 +46,20 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
public static final ParseField QUERY_NAME_FIELD = new ParseField(NAME);
|
||||
|
||||
/**
|
||||
* The default score move for nested queries.
|
||||
* The default score mode for nested queries.
|
||||
*/
|
||||
public static final ScoreMode DEFAULT_SCORE_MODE = ScoreMode.Avg;
|
||||
|
||||
/**
|
||||
* The default value for ignore_unmapped.
|
||||
*/
|
||||
public static final boolean DEFAULT_IGNORE_UNMAPPED = false;
|
||||
|
||||
private static final ParseField SCORE_MODE_FIELD = new ParseField("score_mode");
|
||||
private static final ParseField PATH_FIELD = new ParseField("path");
|
||||
private static final ParseField QUERY_FIELD = new ParseField("query");
|
||||
private static final ParseField INNER_HITS_FIELD = new ParseField("inner_hits");
|
||||
private static final ParseField IGNORE_UNMAPPED_FIELD = new ParseField("ignore_unmapped");
|
||||
|
||||
private final QueryBuilder<?> query;
|
||||
|
||||
|
@ -62,6 +69,8 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
|
||||
private InnerHitBuilder innerHitBuilder;
|
||||
|
||||
private boolean ignoreUnmapped = DEFAULT_IGNORE_UNMAPPED;
|
||||
|
||||
public NestedQueryBuilder(String path, QueryBuilder<?> query) {
|
||||
if (path == null) {
|
||||
throw new IllegalArgumentException("[" + NAME + "] requires 'path' field");
|
||||
|
@ -92,6 +101,7 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
scoreMode = ScoreMode.values()[in.readVInt()];
|
||||
query = in.readQuery();
|
||||
innerHitBuilder = in.readOptionalWriteable(InnerHitBuilder::new);
|
||||
ignoreUnmapped = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,6 +110,7 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
out.writeVInt(scoreMode.ordinal());
|
||||
out.writeQuery(query);
|
||||
out.writeOptionalWriteable(innerHitBuilder);
|
||||
out.writeBoolean(ignoreUnmapped);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,6 +134,25 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the query builder should ignore unmapped paths (and run a
|
||||
* {@link MatchNoDocsQuery} in place of this query) or throw an exception if
|
||||
* the path is unmapped.
|
||||
*/
|
||||
public NestedQueryBuilder ignoreUnmapped(boolean ignoreUnmapped) {
|
||||
this.ignoreUnmapped = ignoreUnmapped;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the query builder will ignore unmapped fields (and run a
|
||||
* {@link MatchNoDocsQuery} in place of this query) or throw an exception if
|
||||
* the path is unmapped.
|
||||
*/
|
||||
public boolean ignoreUnmapped() {
|
||||
return ignoreUnmapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nested query to execute.
|
||||
*/
|
||||
|
@ -150,6 +180,7 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
builder.field(QUERY_FIELD.getPreferredName());
|
||||
query.toXContent(builder, params);
|
||||
builder.field(PATH_FIELD.getPreferredName(), path);
|
||||
builder.field(IGNORE_UNMAPPED_FIELD.getPreferredName(), ignoreUnmapped);
|
||||
if (scoreMode != null) {
|
||||
builder.field(SCORE_MODE_FIELD.getPreferredName(), HasChildQueryBuilder.scoreModeAsString(scoreMode));
|
||||
}
|
||||
|
@ -169,6 +200,7 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
String path = null;
|
||||
String currentFieldName = null;
|
||||
InnerHitBuilder innerHitBuilder = null;
|
||||
boolean ignoreUnmapped = DEFAULT_IGNORE_UNMAPPED;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
|
@ -186,6 +218,8 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
path = parser.text();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.BOOST_FIELD)) {
|
||||
boost = parser.floatValue();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, IGNORE_UNMAPPED_FIELD)) {
|
||||
ignoreUnmapped = parser.booleanValue();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, SCORE_MODE_FIELD)) {
|
||||
scoreMode = HasChildQueryBuilder.parseScoreMode(parser.text());
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.NAME_FIELD)) {
|
||||
|
@ -195,7 +229,8 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
}
|
||||
}
|
||||
}
|
||||
return new NestedQueryBuilder(path, query, scoreMode, innerHitBuilder).queryName(queryName).boost(boost);
|
||||
return new NestedQueryBuilder(path, query, scoreMode, innerHitBuilder).ignoreUnmapped(ignoreUnmapped).queryName(queryName)
|
||||
.boost(boost);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -208,19 +243,24 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
return Objects.equals(query, that.query)
|
||||
&& Objects.equals(path, that.path)
|
||||
&& Objects.equals(scoreMode, that.scoreMode)
|
||||
&& Objects.equals(innerHitBuilder, that.innerHitBuilder);
|
||||
&& Objects.equals(innerHitBuilder, that.innerHitBuilder)
|
||||
&& Objects.equals(ignoreUnmapped, that.ignoreUnmapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doHashCode() {
|
||||
return Objects.hash(query, path, scoreMode, innerHitBuilder);
|
||||
return Objects.hash(query, path, scoreMode, innerHitBuilder, ignoreUnmapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query doToQuery(QueryShardContext context) throws IOException {
|
||||
ObjectMapper nestedObjectMapper = context.getObjectMapper(path);
|
||||
if (nestedObjectMapper == null) {
|
||||
throw new IllegalStateException("[" + NAME + "] failed to find nested object under path [" + path + "]");
|
||||
if (ignoreUnmapped) {
|
||||
return new MatchNoDocsQuery();
|
||||
} else {
|
||||
throw new IllegalStateException("[" + NAME + "] failed to find nested object under path [" + path + "]");
|
||||
}
|
||||
}
|
||||
if (!nestedObjectMapper.nested().isNested()) {
|
||||
throw new IllegalStateException("[" + NAME + "] nested object under path [" + path + "] is not of nested type");
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.apache.lucene.index.Term;
|
|||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.DocValuesTermsQuery;
|
||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
|
@ -43,12 +44,20 @@ public final class ParentIdQueryBuilder extends AbstractQueryBuilder<ParentIdQue
|
|||
public static final String NAME = "parent_id";
|
||||
public static final ParseField QUERY_NAME_FIELD = new ParseField(NAME);
|
||||
|
||||
/**
|
||||
* The default value for ignore_unmapped.
|
||||
*/
|
||||
public static final boolean DEFAULT_IGNORE_UNMAPPED = false;
|
||||
|
||||
private static final ParseField ID_FIELD = new ParseField("id");
|
||||
private static final ParseField TYPE_FIELD = new ParseField("type", "child_type");
|
||||
private static final ParseField IGNORE_UNMAPPED_FIELD = new ParseField("ignore_unmapped");
|
||||
|
||||
private final String type;
|
||||
private final String id;
|
||||
|
||||
private boolean ignoreUnmapped = false;
|
||||
|
||||
public ParentIdQueryBuilder(String type, String id) {
|
||||
this.type = type;
|
||||
this.id = id;
|
||||
|
@ -61,12 +70,14 @@ public final class ParentIdQueryBuilder extends AbstractQueryBuilder<ParentIdQue
|
|||
super(in);
|
||||
type = in.readString();
|
||||
id = in.readString();
|
||||
ignoreUnmapped = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doWriteTo(StreamOutput out) throws IOException {
|
||||
out.writeString(type);
|
||||
out.writeString(id);
|
||||
out.writeBoolean(ignoreUnmapped);
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
|
@ -77,11 +88,31 @@ public final class ParentIdQueryBuilder extends AbstractQueryBuilder<ParentIdQue
|
|||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the query builder should ignore unmapped types (and run a
|
||||
* {@link MatchNoDocsQuery} in place of this query) or throw an exception if
|
||||
* the type is unmapped.
|
||||
*/
|
||||
public ParentIdQueryBuilder ignoreUnmapped(boolean ignoreUnmapped) {
|
||||
this.ignoreUnmapped = ignoreUnmapped;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the query builder will ignore unmapped types (and run a
|
||||
* {@link MatchNoDocsQuery} in place of this query) or throw an exception if
|
||||
* the type is unmapped.
|
||||
*/
|
||||
public boolean ignoreUnmapped() {
|
||||
return ignoreUnmapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(NAME);
|
||||
builder.field(TYPE_FIELD.getPreferredName(), type);
|
||||
builder.field(ID_FIELD.getPreferredName(), id);
|
||||
builder.field(IGNORE_UNMAPPED_FIELD.getPreferredName(), ignoreUnmapped);
|
||||
printBoostAndQueryName(builder);
|
||||
builder.endObject();
|
||||
}
|
||||
|
@ -93,6 +124,7 @@ public final class ParentIdQueryBuilder extends AbstractQueryBuilder<ParentIdQue
|
|||
String id = null;
|
||||
String queryName = null;
|
||||
String currentFieldName = null;
|
||||
boolean ignoreUnmapped = DEFAULT_IGNORE_UNMAPPED;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
|
@ -102,6 +134,8 @@ public final class ParentIdQueryBuilder extends AbstractQueryBuilder<ParentIdQue
|
|||
type = parser.text();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, ID_FIELD)) {
|
||||
id = parser.text();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, IGNORE_UNMAPPED_FIELD)) {
|
||||
ignoreUnmapped = parser.booleanValue();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.BOOST_FIELD)) {
|
||||
boost = parser.floatValue();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.NAME_FIELD)) {
|
||||
|
@ -116,6 +150,7 @@ public final class ParentIdQueryBuilder extends AbstractQueryBuilder<ParentIdQue
|
|||
ParentIdQueryBuilder queryBuilder = new ParentIdQueryBuilder(type, id);
|
||||
queryBuilder.queryName(queryName);
|
||||
queryBuilder.boost(boost);
|
||||
queryBuilder.ignoreUnmapped(ignoreUnmapped);
|
||||
return queryBuilder;
|
||||
}
|
||||
|
||||
|
@ -124,7 +159,11 @@ public final class ParentIdQueryBuilder extends AbstractQueryBuilder<ParentIdQue
|
|||
protected Query doToQuery(QueryShardContext context) throws IOException {
|
||||
DocumentMapper childDocMapper = context.getMapperService().documentMapper(type);
|
||||
if (childDocMapper == null) {
|
||||
throw new QueryShardException(context, "[" + NAME + "] no mapping found for type [" + type + "]");
|
||||
if (ignoreUnmapped) {
|
||||
return new MatchNoDocsQuery();
|
||||
} else {
|
||||
throw new QueryShardException(context, "[" + NAME + "] no mapping found for type [" + type + "]");
|
||||
}
|
||||
}
|
||||
ParentFieldMapper parentFieldMapper = childDocMapper.parentFieldMapper();
|
||||
if (parentFieldMapper.active() == false) {
|
||||
|
@ -141,12 +180,14 @@ public final class ParentIdQueryBuilder extends AbstractQueryBuilder<ParentIdQue
|
|||
|
||||
@Override
|
||||
protected boolean doEquals(ParentIdQueryBuilder that) {
|
||||
return Objects.equals(type, that.type) && Objects.equals(id, that.id);
|
||||
return Objects.equals(type, that.type)
|
||||
&& Objects.equals(id, that.id)
|
||||
&& Objects.equals(ignoreUnmapped, that.ignoreUnmapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doHashCode() {
|
||||
return Objects.hash(type, id);
|
||||
return Objects.hash(type, id, ignoreUnmapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.apache.lucene.queries.TermsQuery;
|
|||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.ConstantScoreQuery;
|
||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
|
@ -55,9 +56,10 @@ import org.junit.BeforeClass;
|
|||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQueryBuilder> {
|
||||
|
@ -124,7 +126,7 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
|
|||
randomBoolean() ? null : 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))).ignoreUnmapped(randomBoolean());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -217,6 +219,7 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
|
|||
" \"score_mode\" : \"avg\",\n" +
|
||||
" \"min_children\" : 883170873,\n" +
|
||||
" \"max_children\" : 1217235442,\n" +
|
||||
" \"ignore_unmapped\" : false,\n" +
|
||||
" \"boost\" : 2.0,\n" +
|
||||
" \"_name\" : \"WNzYMJKRwePuRBh\",\n" +
|
||||
" \"inner_hits\" : {\n" +
|
||||
|
@ -386,4 +389,17 @@ public class HasChildQueryBuilderTests extends AbstractQueryTestCase<HasChildQue
|
|||
assertThat(e.getMessage(), is("No score mode for child query [unrecognized value] found"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testIgnoreUnmapped() throws IOException {
|
||||
final HasChildQueryBuilder queryBuilder = new HasChildQueryBuilder("unmapped", new MatchAllQueryBuilder());
|
||||
queryBuilder.ignoreUnmapped(true);
|
||||
Query query = queryBuilder.toQuery(queryShardContext());
|
||||
assertThat(query, notNullValue());
|
||||
assertThat(query, instanceOf(MatchNoDocsQuery.class));
|
||||
|
||||
final HasChildQueryBuilder failingQueryBuilder = new HasChildQueryBuilder("unmapped", new MatchAllQueryBuilder());
|
||||
failingQueryBuilder.ignoreUnmapped(false);
|
||||
QueryShardException e = expectThrows(QueryShardException.class, () -> failingQueryBuilder.toQuery(queryShardContext()));
|
||||
assertThat(e.getMessage(), containsString("[" + HasChildQueryBuilder.NAME + "] no mapping found for type [unmapped]"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.elasticsearch.index.query;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
|
||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
|
@ -45,9 +47,10 @@ import org.junit.BeforeClass;
|
|||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
|
||||
public class HasParentQueryBuilderTests extends AbstractQueryTestCase<HasParentQueryBuilder> {
|
||||
protected static final String PARENT_TYPE = "parent";
|
||||
|
@ -109,7 +112,7 @@ public class HasParentQueryBuilderTests extends AbstractQueryTestCase<HasParentQ
|
|||
randomBoolean() ? null : 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))).ignoreUnmapped(randomBoolean());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -257,6 +260,7 @@ public class HasParentQueryBuilderTests extends AbstractQueryTestCase<HasParentQ
|
|||
" },\n" +
|
||||
" \"parent_type\" : \"blog\",\n" +
|
||||
" \"score\" : true,\n" +
|
||||
" \"ignore_unmapped\" : false,\n" +
|
||||
" \"boost\" : 1.0\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
@ -265,4 +269,18 @@ public class HasParentQueryBuilderTests extends AbstractQueryTestCase<HasParentQ
|
|||
assertEquals(json, "blog", parsed.type());
|
||||
assertEquals(json, "something", ((TermQueryBuilder) parsed.query()).value());
|
||||
}
|
||||
|
||||
public void testIgnoreUnmapped() throws IOException {
|
||||
final HasParentQueryBuilder queryBuilder = new HasParentQueryBuilder("unmapped", new MatchAllQueryBuilder());
|
||||
queryBuilder.ignoreUnmapped(true);
|
||||
Query query = queryBuilder.toQuery(queryShardContext());
|
||||
assertThat(query, notNullValue());
|
||||
assertThat(query, instanceOf(MatchNoDocsQuery.class));
|
||||
|
||||
final HasParentQueryBuilder failingQueryBuilder = new HasParentQueryBuilder("unmapped", new MatchAllQueryBuilder());
|
||||
failingQueryBuilder.ignoreUnmapped(false);
|
||||
QueryShardException e = expectThrows(QueryShardException.class, () -> failingQueryBuilder.toQuery(queryShardContext()));
|
||||
assertThat(e.getMessage(),
|
||||
containsString("[" + HasParentQueryBuilder.NAME + "] query configured 'parent_type' [unmapped] is not a valid type"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
package org.elasticsearch.index.query;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
|
||||
|
||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.apache.lucene.search.join.ToParentBlockJoinQuery;
|
||||
|
@ -38,6 +40,8 @@ import java.io.IOException;
|
|||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
|
||||
public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBuilder> {
|
||||
|
||||
|
@ -87,7 +91,7 @@ public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBu
|
|||
SearchContext.current() == null ? null : new InnerHitBuilder()
|
||||
.setName(randomAsciiOfLengthBetween(1, 10))
|
||||
.setSize(randomIntBetween(0, 100))
|
||||
.addSort(new FieldSortBuilder(STRING_FIELD_NAME).order(SortOrder.ASC)));
|
||||
.addSort(new FieldSortBuilder(STRING_FIELD_NAME).order(SortOrder.ASC))).ignoreUnmapped(randomBoolean());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -176,6 +180,7 @@ public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBu
|
|||
" }\n" +
|
||||
" },\n" +
|
||||
" \"path\" : \"obj1\",\n" +
|
||||
" \"ignore_unmapped\" : false,\n" +
|
||||
" \"score_mode\" : \"avg\",\n" +
|
||||
" \"boost\" : 1.0\n" +
|
||||
" }\n" +
|
||||
|
@ -186,4 +191,17 @@ public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBu
|
|||
|
||||
assertEquals(json, ScoreMode.Avg, parsed.scoreMode());
|
||||
}
|
||||
|
||||
public void testIgnoreUnmapped() throws IOException {
|
||||
final NestedQueryBuilder queryBuilder = new NestedQueryBuilder("unmapped", new MatchAllQueryBuilder());
|
||||
queryBuilder.ignoreUnmapped(true);
|
||||
Query query = queryBuilder.toQuery(queryShardContext());
|
||||
assertThat(query, notNullValue());
|
||||
assertThat(query, instanceOf(MatchNoDocsQuery.class));
|
||||
|
||||
final NestedQueryBuilder failingQueryBuilder = new NestedQueryBuilder("unmapped", new MatchAllQueryBuilder());
|
||||
failingQueryBuilder.ignoreUnmapped(false);
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class, () -> failingQueryBuilder.toQuery(queryShardContext()));
|
||||
assertThat(e.getMessage(), containsString("[" + NestedQueryBuilder.NAME + "] failed to find nested object under path [unmapped]"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.elasticsearch.index.query;
|
|||
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.DocValuesTermsQuery;
|
||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
|
@ -34,6 +35,10 @@ import org.hamcrest.Matchers;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
|
||||
public class ParentIdQueryBuilderTests extends AbstractQueryTestCase<ParentIdQueryBuilder> {
|
||||
|
||||
protected static final String PARENT_TYPE = "parent";
|
||||
|
@ -84,7 +89,7 @@ public class ParentIdQueryBuilderTests extends AbstractQueryTestCase<ParentIdQue
|
|||
|
||||
@Override
|
||||
protected ParentIdQueryBuilder doCreateTestQueryBuilder() {
|
||||
return new ParentIdQueryBuilder(CHILD_TYPE, randomAsciiOfLength(4));
|
||||
return new ParentIdQueryBuilder(CHILD_TYPE, randomAsciiOfLength(4)).ignoreUnmapped(randomBoolean());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -108,6 +113,7 @@ public class ParentIdQueryBuilderTests extends AbstractQueryTestCase<ParentIdQue
|
|||
" \"parent_id\" : {\n" +
|
||||
" \"type\" : \"child\",\n" +
|
||||
" \"id\" : \"123\",\n" +
|
||||
" \"ignore_unmapped\" : false,\n" +
|
||||
" \"boost\" : 3.0,\n" +
|
||||
" \"_name\" : \"name\"" +
|
||||
" }\n" +
|
||||
|
@ -120,4 +126,17 @@ public class ParentIdQueryBuilderTests extends AbstractQueryTestCase<ParentIdQue
|
|||
assertThat(queryBuilder.queryName(), Matchers.equalTo("name"));
|
||||
}
|
||||
|
||||
public void testIgnoreUnmapped() throws IOException {
|
||||
final ParentIdQueryBuilder queryBuilder = new ParentIdQueryBuilder("unmapped", "foo");
|
||||
queryBuilder.ignoreUnmapped(true);
|
||||
Query query = queryBuilder.toQuery(queryShardContext());
|
||||
assertThat(query, notNullValue());
|
||||
assertThat(query, instanceOf(MatchNoDocsQuery.class));
|
||||
|
||||
final ParentIdQueryBuilder failingQueryBuilder = new ParentIdQueryBuilder("unmapped", "foo");
|
||||
failingQueryBuilder.ignoreUnmapped(false);
|
||||
QueryShardException e = expectThrows(QueryShardException.class, () -> failingQueryBuilder.toQuery(queryShardContext()));
|
||||
assertThat(e.getMessage(), containsString("[" + ParentIdQueryBuilder.NAME + "] no mapping found for type [unmapped]"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -72,3 +72,12 @@ a match:
|
|||
|
||||
The `min_children` and `max_children` parameters can be combined with
|
||||
the `score_mode` parameter.
|
||||
|
||||
[float]
|
||||
==== Ignore Unmapped
|
||||
|
||||
When set to `true` the `ignore_unmapped` option will ignore an unmapped `type`
|
||||
and will not match any documents for this query. This can be useful when
|
||||
querying multiple indexes which might have different mappings. When set to
|
||||
`false` (the default value) the query will throw an exception if the `type`
|
||||
is not mapped.
|
||||
|
|
|
@ -46,3 +46,12 @@ matching parent document. The score mode can be specified with the
|
|||
}
|
||||
}
|
||||
--------------------------------------------------
|
||||
|
||||
[float]
|
||||
==== Ignore Unmapped
|
||||
|
||||
When set to `true` the `ignore_unmapped` option will ignore an unmapped `type`
|
||||
and will not match any documents for this query. This can be useful when
|
||||
querying multiple indexes which might have different mappings. When set to
|
||||
`false` (the default value) the query will throw an exception if the `type`
|
||||
is not mapped.
|
||||
|
|
|
@ -55,6 +55,12 @@ The `score_mode` allows to set how inner children matching affects
|
|||
scoring of parent. It defaults to `avg`, but can be `sum`, `min`,
|
||||
`max` and `none`.
|
||||
|
||||
There is also an `ignore_unmapped` option which, when set to `true` will
|
||||
ignore an unmapped `path` and will not match any documents for this query.
|
||||
This can be useful when querying multiple indexes which might have different
|
||||
mappings. When set to `false` (the default value) the query will throw an
|
||||
exception if the `path` is not mapped.
|
||||
|
||||
Multi level nesting is automatically supported, and detected, resulting
|
||||
in an inner nested query to automatically match the relevant nesting
|
||||
level (and not root) if it exists within another nested query.
|
||||
|
|
|
@ -8,10 +8,10 @@ The `parent_id` query can be used to find child documents which belong to a part
|
|||
[source,js]
|
||||
--------------------------------------------------
|
||||
{
|
||||
"parent_id" : {
|
||||
"type" : "blog_tag",
|
||||
"id" : "1"
|
||||
}
|
||||
"parent_id" : {
|
||||
"type" : "blog_tag",
|
||||
"id" : "1"
|
||||
}
|
||||
}
|
||||
--------------------------------------------------
|
||||
|
||||
|
@ -40,4 +40,9 @@ This query has two required parameters:
|
|||
[horizontal]
|
||||
`type`:: The **child** type. This must be a type with `_parent` field.
|
||||
|
||||
`id`:: The required parent id select documents must referrer to.
|
||||
`id`:: The required parent id select documents must referrer to.
|
||||
|
||||
`ignore_unmapped`:: When set to `true` this will ignore an unmapped `type` and will not match any
|
||||
documents for this query. This can be useful when querying multiple indexes
|
||||
which might have different mappings. When set to `false` (the default value)
|
||||
the query will throw an exception if the `type` is not mapped.
|
||||
|
|
Loading…
Reference in New Issue