@@ -63,6 +63,11 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
6363 * The default minimum number of children that are required to match for the parent to be considered a match.
6464 */
6565 public static final int DEFAULT_MIN_CHILDREN = 0 ;
66+
67+ /**
68+ * The default value for ignore_unmapped.
69+ */
70+ public static final boolean DEFAULT_IGNORE_UNMAPPED = false ;
6671 /*
6772 * The default score mode that is used to combine score coming from multiple parent documents.
6873 */
@@ -74,6 +79,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
7479 private static final ParseField MIN_CHILDREN_FIELD = new ParseField ("min_children" );
7580 private static final ParseField SCORE_MODE_FIELD = new ParseField ("score_mode" );
7681 private static final ParseField INNER_HITS_FIELD = new ParseField ("inner_hits" );
82+ private static final ParseField IGNORE_UNMAPPED_FIELD = new ParseField ("ignore_unmapped" );
7783
7884 private final QueryBuilder <?> query ;
7985
@@ -87,6 +93,8 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
8793
8894 private InnerHitBuilder innerHitBuilder ;
8995
96+ private boolean ignoreUnmapped = false ;
97+
9098
9199 public HasChildQueryBuilder (String type , QueryBuilder <?> query , int maxChildren , int minChildren , ScoreMode scoreMode ,
92100 InnerHitBuilder innerHitBuilder ) {
@@ -123,6 +131,7 @@ public HasChildQueryBuilder(StreamInput in) throws IOException {
123131 scoreMode = ScoreMode .values ()[in .readVInt ()];
124132 query = in .readQuery ();
125133 innerHitBuilder = in .readOptionalWriteable (InnerHitBuilder ::new );
134+ ignoreUnmapped = in .readBoolean ();
126135 }
127136
128137 @ Override
@@ -133,6 +142,7 @@ protected void doWriteTo(StreamOutput out) throws IOException {
133142 out .writeVInt (scoreMode .ordinal ());
134143 out .writeQuery (query );
135144 out .writeOptionalWriteable (innerHitBuilder );
145+ out .writeBoolean (ignoreUnmapped );
136146 }
137147
138148 /**
@@ -220,6 +230,25 @@ public int minChildren() {
220230 */
221231 public int maxChildren () { return maxChildren ; }
222232
233+ /**
234+ * Sets whether the query builder should ignore unmapped types (and run a
235+ * {@link MatchNoDocsQuery} in place of this query) or throw an exception if
236+ * the type is unmapped.
237+ */
238+ public HasChildQueryBuilder ignoreUnmapped (boolean ignoreUnmapped ) {
239+ this .ignoreUnmapped = ignoreUnmapped ;
240+ return this ;
241+ }
242+
243+ /**
244+ * Gets whether the query builder will ignore unmapped types (and run a
245+ * {@link MatchNoDocsQuery} in place of this query) or throw an exception if
246+ * the type is unmapped.
247+ */
248+ public boolean ignoreUnmapped () {
249+ return ignoreUnmapped ;
250+ }
251+
223252 @ Override
224253 protected void doXContent (XContentBuilder builder , Params params ) throws IOException {
225254 builder .startObject (NAME );
@@ -229,6 +258,7 @@ protected void doXContent(XContentBuilder builder, Params params) throws IOExcep
229258 builder .field (SCORE_MODE_FIELD .getPreferredName (), scoreModeAsString (scoreMode ));
230259 builder .field (MIN_CHILDREN_FIELD .getPreferredName (), minChildren );
231260 builder .field (MAX_CHILDREN_FIELD .getPreferredName (), maxChildren );
261+ builder .field (IGNORE_UNMAPPED_FIELD .getPreferredName (), ignoreUnmapped );
232262 printBoostAndQueryName (builder );
233263 if (innerHitBuilder != null ) {
234264 builder .field (INNER_HITS_FIELD .getPreferredName (), innerHitBuilder , params );
@@ -243,6 +273,7 @@ public static HasChildQueryBuilder fromXContent(QueryParseContext parseContext)
243273 ScoreMode scoreMode = HasChildQueryBuilder .DEFAULT_SCORE_MODE ;
244274 int minChildren = HasChildQueryBuilder .DEFAULT_MIN_CHILDREN ;
245275 int maxChildren = HasChildQueryBuilder .DEFAULT_MAX_CHILDREN ;
276+ boolean ignoreUnmapped = DEFAULT_IGNORE_UNMAPPED ;
246277 String queryName = null ;
247278 InnerHitBuilder innerHitBuilder = null ;
248279 String currentFieldName = null ;
@@ -272,6 +303,8 @@ public static HasChildQueryBuilder fromXContent(QueryParseContext parseContext)
272303 minChildren = parser .intValue (true );
273304 } else if (parseContext .parseFieldMatcher ().match (currentFieldName , MAX_CHILDREN_FIELD )) {
274305 maxChildren = parser .intValue (true );
306+ } else if (parseContext .parseFieldMatcher ().match (currentFieldName , IGNORE_UNMAPPED_FIELD )) {
307+ ignoreUnmapped = parser .booleanValue ();
275308 } else if (parseContext .parseFieldMatcher ().match (currentFieldName , AbstractQueryBuilder .NAME_FIELD )) {
276309 queryName = parser .text ();
277310 } else {
@@ -283,6 +316,7 @@ public static HasChildQueryBuilder fromXContent(QueryParseContext parseContext)
283316 scoreMode , innerHitBuilder );
284317 hasChildQueryBuilder .queryName (queryName );
285318 hasChildQueryBuilder .boost (boost );
319+ hasChildQueryBuilder .ignoreUnmapped (ignoreUnmapped );
286320 return hasChildQueryBuilder ;
287321 }
288322
@@ -331,7 +365,11 @@ protected Query doToQuery(QueryShardContext context) throws IOException {
331365 }
332366 DocumentMapper childDocMapper = context .getMapperService ().documentMapper (type );
333367 if (childDocMapper == null ) {
334- throw new QueryShardException (context , "[" + NAME + "] no mapping found for type [" + type + "]" );
368+ if (ignoreUnmapped ) {
369+ return new MatchNoDocsQuery ();
370+ } else {
371+ throw new QueryShardException (context , "[" + NAME + "] no mapping found for type [" + type + "]" );
372+ }
335373 }
336374 ParentFieldMapper parentFieldMapper = childDocMapper .parentFieldMapper ();
337375 if (parentFieldMapper .active () == false ) {
@@ -344,8 +382,8 @@ protected Query doToQuery(QueryShardContext context) throws IOException {
344382 String parentType = parentFieldMapper .type ();
345383 DocumentMapper parentDocMapper = context .getMapperService ().documentMapper (parentType );
346384 if (parentDocMapper == null ) {
347- throw new QueryShardException (context , "[" + NAME + "] Type [" + type + "] points to a non existent parent type ["
348- + parentType + "]" );
385+ throw new QueryShardException (context ,
386+ "[" + NAME + "] Type [" + type + "] points to a non existent parent type [" + parentType + "]" );
349387 }
350388
351389 if (maxChildren > 0 && maxChildren < minChildren ) {
@@ -464,12 +502,13 @@ protected boolean doEquals(HasChildQueryBuilder that) {
464502 && Objects .equals (scoreMode , that .scoreMode )
465503 && Objects .equals (minChildren , that .minChildren )
466504 && Objects .equals (maxChildren , that .maxChildren )
467- && Objects .equals (innerHitBuilder , that .innerHitBuilder );
505+ && Objects .equals (innerHitBuilder , that .innerHitBuilder )
506+ && Objects .equals (ignoreUnmapped , that .ignoreUnmapped );
468507 }
469508
470509 @ Override
471510 protected int doHashCode () {
472- return Objects .hash (query , type , scoreMode , minChildren , maxChildren , innerHitBuilder );
511+ return Objects .hash (query , type , scoreMode , minChildren , maxChildren , innerHitBuilder , ignoreUnmapped );
473512 }
474513
475514 @ Override
0 commit comments