diff options
author | Christoph Büscher <christoph@elastic.co> | 2016-04-20 13:19:12 +0200 |
---|---|---|
committer | Christoph Büscher <christoph@elastic.co> | 2016-06-02 11:25:56 +0200 |
commit | 359f45988fa5550ff44a0f805fa050eb9a221405 (patch) | |
tree | 6facefbd87f2ed55d9f2142b7896d6f65796bf05 /core/src/main/java/org/elasticsearch/index/query | |
parent | b2724c0d08267486efc261a30bdb686cb9977f5d (diff) |
Handle empty query bodies at parse time and remove EmptyQueryBuilder
Currently we support empty query clauses like the filter in
"constant_score" : { "filter" : { } }
How these clauses are handled depends on the surrounding query.
They later are either ignored, converted to match all or no documents or
passed up further in the query hierarchy. During parsing these claues are
currently represented as EmptyQueryBuilders. When not handled anywhere else,
these special cases need to be checked for on the shard when building the
lucene query.
This is trappy, so this PR changes the parsing of compound queries. Instead
of returning QueryBuilder, the core query parsing method
QueryShardContext#parseInnerQueryBuilder() now return an Optional which can
be empty in the case of empty query clauses. This has the advantage of forcing
callers to deal with this sooner or later. When encountering empty Optionals,
compound query builders now have the choice to ignore them, pass them on or
rewrite to a different query, depending on context.
Diffstat (limited to 'core/src/main/java/org/elasticsearch/index/query')
52 files changed, 275 insertions, 274 deletions
diff --git a/core/src/main/java/org/elasticsearch/index/query/BoolQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/BoolQueryBuilder.java index e5aa774add..863bdb25c7 100644 --- a/core/src/main/java/org/elasticsearch/index/query/BoolQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/BoolQueryBuilder.java @@ -37,6 +37,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.function.Consumer; import static org.elasticsearch.common.lucene.search.Queries.fixNegativeQueryIfNeeded; @@ -300,7 +301,7 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> { builder.endArray(); } - public static BoolQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException, ParsingException { + public static Optional<BoolQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException, ParsingException { XContentParser parser = parseContext.parser(); boolean disableCoord = BoolQueryBuilder.DISABLE_COORD_DEFAULT; @@ -316,7 +317,6 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> { String currentFieldName = null; XContentParser.Token token; - QueryBuilder query; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); @@ -325,21 +325,17 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> { } else if (token == XContentParser.Token.START_OBJECT) { switch (currentFieldName) { case MUST: - query = parseContext.parseInnerQueryBuilder(); - mustClauses.add(query); + parseContext.parseInnerQueryBuilder().ifPresent(mustClauses::add); break; case SHOULD: - query = parseContext.parseInnerQueryBuilder(); - shouldClauses.add(query); + parseContext.parseInnerQueryBuilder().ifPresent(shouldClauses::add); break; case FILTER: - query = parseContext.parseInnerQueryBuilder(); - filterClauses.add(query); + parseContext.parseInnerQueryBuilder().ifPresent(filterClauses::add); break; case MUST_NOT: case MUSTNOT: - query = parseContext.parseInnerQueryBuilder(); - mustNotClauses.add(query); + parseContext.parseInnerQueryBuilder().ifPresent(mustNotClauses::add); break; default: throw new ParsingException(parser.getTokenLocation(), "[bool] query does not support [" + currentFieldName + "]"); @@ -348,21 +344,17 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> { while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { switch (currentFieldName) { case MUST: - query = parseContext.parseInnerQueryBuilder(); - mustClauses.add(query); + parseContext.parseInnerQueryBuilder().ifPresent(mustClauses::add); break; case SHOULD: - query = parseContext.parseInnerQueryBuilder(); - shouldClauses.add(query); + parseContext.parseInnerQueryBuilder().ifPresent(shouldClauses::add); break; case FILTER: - query = parseContext.parseInnerQueryBuilder(); - filterClauses.add(query); + parseContext.parseInnerQueryBuilder().ifPresent(filterClauses::add); break; case MUST_NOT: case MUSTNOT: - query = parseContext.parseInnerQueryBuilder(); - mustNotClauses.add(query); + parseContext.parseInnerQueryBuilder().ifPresent(mustNotClauses::add); break; default: throw new ParsingException(parser.getTokenLocation(), "bool query does not support [" + currentFieldName + "]"); @@ -404,7 +396,7 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> { boolQuery.adjustPureNegative(adjustPureNegative); boolQuery.minimumNumberShouldMatch(minimumShouldMatch); boolQuery.queryName(queryName); - return boolQuery; + return Optional.of(boolQuery); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/BoostingQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/BoostingQueryBuilder.java index 496cb7ec8a..3afa4339b5 100644 --- a/core/src/main/java/org/elasticsearch/index/query/BoostingQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/BoostingQueryBuilder.java @@ -31,6 +31,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; import java.util.Map; import java.util.Objects; +import java.util.Optional; /** * The BoostingQuery class can be used to effectively demote results that match a given query. @@ -138,12 +139,12 @@ public class BoostingQueryBuilder extends AbstractQueryBuilder<BoostingQueryBuil builder.endObject(); } - public static BoostingQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<BoostingQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); - QueryBuilder positiveQuery = null; + Optional<QueryBuilder> positiveQuery = null; boolean positiveQueryFound = false; - QueryBuilder negativeQuery = null; + Optional<QueryBuilder> negativeQuery = null; boolean negativeQueryFound = false; float boost = AbstractQueryBuilder.DEFAULT_BOOST; float negativeBoost = -1; @@ -187,12 +188,15 @@ public class BoostingQueryBuilder extends AbstractQueryBuilder<BoostingQueryBuil throw new ParsingException(parser.getTokenLocation(), "[boosting] query requires 'negative_boost' to be set to be a positive value'"); } + if (positiveQuery.isPresent() == false || negativeQuery.isPresent() == false) { + return Optional.empty(); + } - BoostingQueryBuilder boostingQuery = new BoostingQueryBuilder(positiveQuery, negativeQuery); + BoostingQueryBuilder boostingQuery = new BoostingQueryBuilder(positiveQuery.get(), negativeQuery.get()); boostingQuery.negativeBoost(negativeBoost); boostingQuery.boost(boost); boostingQuery.queryName(queryName); - return boostingQuery; + return Optional.of(boostingQuery); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/CommonTermsQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/CommonTermsQueryBuilder.java index f7b35d8dfa..692c157c1b 100644 --- a/core/src/main/java/org/elasticsearch/index/query/CommonTermsQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/CommonTermsQueryBuilder.java @@ -40,6 +40,7 @@ import org.elasticsearch.index.mapper.MappedFieldType; import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * CommonTermsQuery query is a query that executes high-frequency terms in a @@ -263,7 +264,7 @@ public class CommonTermsQueryBuilder extends AbstractQueryBuilder<CommonTermsQue builder.endObject(); } - public static CommonTermsQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<CommonTermsQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); XContentParser.Token token = parser.nextToken(); if (token != XContentParser.Token.FIELD_NAME) { @@ -352,7 +353,7 @@ public class CommonTermsQueryBuilder extends AbstractQueryBuilder<CommonTermsQue if (text == null) { throw new ParsingException(parser.getTokenLocation(), "No text specified for text query"); } - return new CommonTermsQueryBuilder(fieldName, text) + return Optional.of(new CommonTermsQueryBuilder(fieldName, text) .lowFreqMinimumShouldMatch(lowFreqMinimumShouldMatch) .highFreqMinimumShouldMatch(highFreqMinimumShouldMatch) .analyzer(analyzer) @@ -361,7 +362,7 @@ public class CommonTermsQueryBuilder extends AbstractQueryBuilder<CommonTermsQue .disableCoord(disableCoord) .cutoffFrequency(cutoffFrequency) .boost(boost) - .queryName(queryName); + .queryName(queryName)); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/ConstantScoreQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/ConstantScoreQueryBuilder.java index 306a456857..44b4458b57 100644 --- a/core/src/main/java/org/elasticsearch/index/query/ConstantScoreQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/ConstantScoreQueryBuilder.java @@ -31,6 +31,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; import java.util.Map; import java.util.Objects; +import java.util.Optional; /** * A query that wraps a filter and simply returns a constant score equal to the @@ -87,10 +88,10 @@ public class ConstantScoreQueryBuilder extends AbstractQueryBuilder<ConstantScor builder.endObject(); } - public static ConstantScoreQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<ConstantScoreQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); - QueryBuilder query = null; + Optional<QueryBuilder> query = Optional.empty(); boolean queryFound = false; String queryName = null; float boost = AbstractQueryBuilder.DEFAULT_BOOST; @@ -131,10 +132,15 @@ public class ConstantScoreQueryBuilder extends AbstractQueryBuilder<ConstantScor throw new ParsingException(parser.getTokenLocation(), "[constant_score] requires a 'filter' element"); } - ConstantScoreQueryBuilder constantScoreBuilder = new ConstantScoreQueryBuilder(query); + if (query.isPresent() == false) { + // if inner query is empty, bubble this up to caller so they can decide how to deal with it + return Optional.empty(); + } + + ConstantScoreQueryBuilder constantScoreBuilder = new ConstantScoreQueryBuilder(query.get()); constantScoreBuilder.boost(boost); constantScoreBuilder.queryName(queryName); - return constantScoreBuilder; + return Optional.of(constantScoreBuilder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/DisMaxQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/DisMaxQueryBuilder.java index f38b2c09b1..e480417e8f 100644 --- a/core/src/main/java/org/elasticsearch/index/query/DisMaxQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/DisMaxQueryBuilder.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; +import java.util.Optional; /** * A query that generates the union of documents produced by its sub-queries, and that scores each document @@ -122,7 +123,7 @@ public class DisMaxQueryBuilder extends AbstractQueryBuilder<DisMaxQueryBuilder> builder.endObject(); } - public static DisMaxQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<DisMaxQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); float boost = AbstractQueryBuilder.DEFAULT_BOOST; @@ -140,8 +141,7 @@ public class DisMaxQueryBuilder extends AbstractQueryBuilder<DisMaxQueryBuilder> } else if (token == XContentParser.Token.START_OBJECT) { if (parseContext.getParseFieldMatcher().match(currentFieldName, QUERIES_FIELD)) { queriesFound = true; - QueryBuilder query = parseContext.parseInnerQueryBuilder(); - queries.add(query); + parseContext.parseInnerQueryBuilder().ifPresent(queries::add); } else { throw new ParsingException(parser.getTokenLocation(), "[dis_max] query does not support [" + currentFieldName + "]"); } @@ -149,8 +149,7 @@ public class DisMaxQueryBuilder extends AbstractQueryBuilder<DisMaxQueryBuilder> if (parseContext.getParseFieldMatcher().match(currentFieldName, QUERIES_FIELD)) { queriesFound = true; while (token != XContentParser.Token.END_ARRAY) { - QueryBuilder query = parseContext.parseInnerQueryBuilder(); - queries.add(query); + parseContext.parseInnerQueryBuilder().ifPresent(queries::add); token = parser.nextToken(); } } else { @@ -180,7 +179,7 @@ public class DisMaxQueryBuilder extends AbstractQueryBuilder<DisMaxQueryBuilder> for (QueryBuilder query : queries) { disMaxQuery.add(query); } - return disMaxQuery; + return Optional.of(disMaxQuery); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/EmptyQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/EmptyQueryBuilder.java deleted file mode 100644 index 3d09bb41b0..0000000000 --- a/core/src/main/java/org/elasticsearch/index/query/EmptyQueryBuilder.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.index.query; - -import org.apache.lucene.search.Query; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.xcontent.XContentBuilder; - -import java.io.IOException; - -/** - * A {@link QueryBuilder} that is a stand in replacement for an empty query clause in the DSL. - * The current DSL allows parsing inner queries / filters like "{ }", in order to have a - * valid non-null representation of these clauses that actually do nothing we can use this class. - */ -public final class EmptyQueryBuilder extends AbstractQueryBuilder<EmptyQueryBuilder> { - - public static final String NAME = "empty_query"; - - /** - * Construct an empty query. This query can *technically* be named and given a boost. - */ - public EmptyQueryBuilder() { - } - - /** - * Read from a stream. - */ - public EmptyQueryBuilder(StreamInput in) throws IOException { - super(in); - } - - @Override - protected void doWriteTo(StreamOutput out) throws IOException { - } - - @Override - public String getWriteableName() { - return NAME; - } - - @Override - protected Query doToQuery(QueryShardContext context) throws IOException { - return null; - } - - @Override - public String getName() { - return getWriteableName(); - } - - @Override - protected void doXContent(XContentBuilder builder, Params params) throws IOException { - } - - @Override - protected int doHashCode() { - return 31; - } - - @Override - protected boolean doEquals(EmptyQueryBuilder other) { - return true; - } -} diff --git a/core/src/main/java/org/elasticsearch/index/query/ExistsQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/ExistsQueryBuilder.java index afcff164be..c933bae68c 100644 --- a/core/src/main/java/org/elasticsearch/index/query/ExistsQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/ExistsQueryBuilder.java @@ -37,6 +37,7 @@ import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.Objects; +import java.util.Optional; /** * Constructs a query that only match on documents that the field has a value in them. @@ -85,7 +86,7 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder> builder.endObject(); } - public static ExistsQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<ExistsQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String fieldPattern = null; @@ -121,7 +122,7 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder> ExistsQueryBuilder builder = new ExistsQueryBuilder(fieldPattern); builder.queryName(queryName); builder.boost(boost); - return builder; + return Optional.of(builder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/FieldMaskingSpanQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/FieldMaskingSpanQueryBuilder.java index 0382f353cb..801b0ae5a8 100644 --- a/core/src/main/java/org/elasticsearch/index/query/FieldMaskingSpanQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/FieldMaskingSpanQueryBuilder.java @@ -33,6 +33,7 @@ import org.elasticsearch.index.mapper.MappedFieldType; import java.io.IOException; import java.util.Objects; +import java.util.Optional; public class FieldMaskingSpanQueryBuilder extends AbstractQueryBuilder<FieldMaskingSpanQueryBuilder> implements SpanQueryBuilder { @@ -103,7 +104,7 @@ public class FieldMaskingSpanQueryBuilder extends AbstractQueryBuilder<FieldMask builder.endObject(); } - public static FieldMaskingSpanQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<FieldMaskingSpanQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); float boost = AbstractQueryBuilder.DEFAULT_BOOST; @@ -119,11 +120,11 @@ public class FieldMaskingSpanQueryBuilder extends AbstractQueryBuilder<FieldMask currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { if (parseContext.getParseFieldMatcher().match(currentFieldName, QUERY_FIELD)) { - QueryBuilder query = parseContext.parseInnerQueryBuilder(); - if (!(query instanceof SpanQueryBuilder)) { + Optional<QueryBuilder> query = parseContext.parseInnerQueryBuilder(); + if (query.isPresent() == false || query.get() instanceof SpanQueryBuilder == false) { throw new ParsingException(parser.getTokenLocation(), "[field_masking_span] query must be of type span query"); } - inner = (SpanQueryBuilder) query; + inner = (SpanQueryBuilder) query.get(); } else { throw new ParsingException(parser.getTokenLocation(), "[field_masking_span] query does not support [" + currentFieldName + "]"); @@ -151,7 +152,7 @@ public class FieldMaskingSpanQueryBuilder extends AbstractQueryBuilder<FieldMask FieldMaskingSpanQueryBuilder queryBuilder = new FieldMaskingSpanQueryBuilder(inner, field); queryBuilder.boost(boost); queryBuilder.queryName(queryName); - return queryBuilder; + return Optional.of(queryBuilder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/FuzzyQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/FuzzyQueryBuilder.java index 70b4f5eb7f..6e60c19d2f 100644 --- a/core/src/main/java/org/elasticsearch/index/query/FuzzyQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/FuzzyQueryBuilder.java @@ -37,6 +37,7 @@ import org.elasticsearch.index.query.support.QueryParsers; import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * A Query that does fuzzy matching for a specific value. @@ -257,7 +258,7 @@ public class FuzzyQueryBuilder extends AbstractQueryBuilder<FuzzyQueryBuilder> i builder.endObject(); } - public static FuzzyQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<FuzzyQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); XContentParser.Token token = parser.nextToken(); @@ -317,14 +318,14 @@ public class FuzzyQueryBuilder extends AbstractQueryBuilder<FuzzyQueryBuilder> i if (value == null) { throw new ParsingException(parser.getTokenLocation(), "no value specified for fuzzy query"); } - return new FuzzyQueryBuilder(fieldName, value) + return Optional.of(new FuzzyQueryBuilder(fieldName, value) .fuzziness(fuzziness) .prefixLength(prefixLength) .maxExpansions(maxExpansions) .transpositions(transpositions) .rewrite(rewrite) .boost(boost) - .queryName(queryName); + .queryName(queryName)); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java index 7f5d5e2ec8..c1925fe3f3 100644 --- a/core/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java @@ -43,6 +43,7 @@ import org.elasticsearch.index.search.geo.IndexedGeoBoundingBoxQuery; import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * Creates a Lucene query that will filter for all documents that lie within the specified @@ -385,7 +386,7 @@ public class GeoBoundingBoxQueryBuilder extends AbstractQueryBuilder<GeoBounding builder.endObject(); } - public static GeoBoundingBoxQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<GeoBoundingBoxQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String fieldName = null; @@ -496,7 +497,7 @@ public class GeoBoundingBoxQueryBuilder extends AbstractQueryBuilder<GeoBounding } else { builder.setValidationMethod(GeoValidationMethod.infer(coerce, ignoreMalformed)); } - return builder; + return Optional.of(builder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/GeoDistanceQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/GeoDistanceQueryBuilder.java index 0f2b4694e2..710cb529c0 100644 --- a/core/src/main/java/org/elasticsearch/index/query/GeoDistanceQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/GeoDistanceQueryBuilder.java @@ -45,6 +45,7 @@ import org.elasticsearch.index.search.geo.GeoDistanceRangeQuery; import java.io.IOException; import java.util.Locale; import java.util.Objects; +import java.util.Optional; /** * Filter results of a query to include only those within a specific distance to some @@ -330,7 +331,7 @@ public class GeoDistanceQueryBuilder extends AbstractQueryBuilder<GeoDistanceQue builder.endObject(); } - public static GeoDistanceQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<GeoDistanceQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); XContentParser.Token token; @@ -445,7 +446,7 @@ public class GeoDistanceQueryBuilder extends AbstractQueryBuilder<GeoDistanceQue qb.boost(boost); qb.queryName(queryName); qb.ignoreUnmapped(ignoreUnmapped); - return qb; + return Optional.of(qb); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/GeoDistanceRangeQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/GeoDistanceRangeQueryBuilder.java index ea22461243..06f30a3477 100644 --- a/core/src/main/java/org/elasticsearch/index/query/GeoDistanceRangeQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/GeoDistanceRangeQueryBuilder.java @@ -46,6 +46,7 @@ import org.elasticsearch.index.search.geo.GeoDistanceRangeQuery; import java.io.IOException; import java.util.Locale; import java.util.Objects; +import java.util.Optional; import static org.apache.lucene.spatial.util.GeoEncodingUtils.TOLERANCE; @@ -391,7 +392,7 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan builder.endObject(); } - public static GeoDistanceRangeQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<GeoDistanceRangeQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); XContentParser.Token token; @@ -603,7 +604,7 @@ public class GeoDistanceRangeQueryBuilder extends AbstractQueryBuilder<GeoDistan queryBuilder.setValidationMethod(GeoValidationMethod.infer(coerce, ignoreMalformed)); } queryBuilder.ignoreUnmapped(ignoreUnmapped); - return queryBuilder; + return Optional.of(queryBuilder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/GeoPolygonQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/GeoPolygonQueryBuilder.java index 35ab98e25d..97c9990a9f 100644 --- a/core/src/main/java/org/elasticsearch/index/query/GeoPolygonQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/GeoPolygonQueryBuilder.java @@ -43,6 +43,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Optional; public class GeoPolygonQueryBuilder extends AbstractQueryBuilder<GeoPolygonQueryBuilder> { @@ -241,7 +242,7 @@ public class GeoPolygonQueryBuilder extends AbstractQueryBuilder<GeoPolygonQuery builder.endObject(); } - public static GeoPolygonQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<GeoPolygonQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String fieldName = null; @@ -322,7 +323,7 @@ public class GeoPolygonQueryBuilder extends AbstractQueryBuilder<GeoPolygonQuery builder.boost(boost); } builder.ignoreUnmapped(ignoreUnmapped); - return builder; + return Optional.of(builder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/GeoShapeQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/GeoShapeQueryBuilder.java index 8b3c8a6248..0b04629e2c 100644 --- a/core/src/main/java/org/elasticsearch/index/query/GeoShapeQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/GeoShapeQueryBuilder.java @@ -47,6 +47,7 @@ import org.elasticsearch.index.mapper.geo.GeoShapeFieldMapper; import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * {@link QueryBuilder} that builds a GeoShape Query @@ -453,7 +454,7 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil builder.endObject(); } - public static GeoShapeQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<GeoShapeQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String fieldName = null; @@ -559,7 +560,7 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil } builder.boost(boost); builder.ignoreUnmapped(ignoreUnmapped); - return builder; + return Optional.of(builder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/GeohashCellQuery.java b/core/src/main/java/org/elasticsearch/index/query/GeohashCellQuery.java index 4f34d6db31..f9f21bac7b 100644 --- a/core/src/main/java/org/elasticsearch/index/query/GeohashCellQuery.java +++ b/core/src/main/java/org/elasticsearch/index/query/GeohashCellQuery.java @@ -21,12 +21,12 @@ package org.elasticsearch.index.query; import org.apache.lucene.search.MatchNoDocsQuery; import org.apache.lucene.search.Query; -import org.elasticsearch.common.geo.GeoHashUtils; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.geo.GeoHashUtils; import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.GeoUtils; import org.elasticsearch.common.io.stream.StreamInput; @@ -42,6 +42,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Optional; /** * A geohash cell filter that filters {@link GeoPoint}s by their geohashes. Basically the a @@ -280,7 +281,7 @@ public class GeohashCellQuery { builder.endObject(); } - public static Builder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<Builder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String fieldName = null; @@ -362,7 +363,7 @@ public class GeohashCellQuery { builder.boost(boost); } builder.ignoreUnmapped(ignoreUnmapped); - return builder; + return Optional.of(builder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/HasChildQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/HasChildQueryBuilder.java index 990b5a35fd..410fda41ae 100644 --- a/core/src/main/java/org/elasticsearch/index/query/HasChildQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/HasChildQueryBuilder.java @@ -43,6 +43,7 @@ import java.io.IOException; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; /** * A query builder for <tt>has_child</tt> query. @@ -226,7 +227,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil builder.endObject(); } - public static HasChildQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<HasChildQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); float boost = AbstractQueryBuilder.DEFAULT_BOOST; String childType = null; @@ -238,7 +239,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil InnerHitBuilder innerHitBuilder = null; String currentFieldName = null; XContentParser.Token token; - QueryBuilder iqb = null; + Optional<QueryBuilder> iqb = Optional.empty(); while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); @@ -272,7 +273,13 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil } } } - HasChildQueryBuilder hasChildQueryBuilder = new HasChildQueryBuilder(childType, iqb, scoreMode); + + if (iqb.isPresent() == false) { + // if inner query is empty, bubble this up to caller so they can decide how to deal with it + return Optional.empty(); + } + + HasChildQueryBuilder hasChildQueryBuilder = new HasChildQueryBuilder(childType, iqb.get(), scoreMode); if (innerHitBuilder != null) { hasChildQueryBuilder.innerHit(innerHitBuilder); } @@ -280,7 +287,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil hasChildQueryBuilder.queryName(queryName); hasChildQueryBuilder.boost(boost); hasChildQueryBuilder.ignoreUnmapped(ignoreUnmapped); - return hasChildQueryBuilder; + return Optional.of(hasChildQueryBuilder); } public static ScoreMode parseScoreMode(String scoreModeString) { diff --git a/core/src/main/java/org/elasticsearch/index/query/HasParentQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/HasParentQueryBuilder.java index 96356c276e..7e788a16e8 100644 --- a/core/src/main/java/org/elasticsearch/index/query/HasParentQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/HasParentQueryBuilder.java @@ -38,6 +38,7 @@ import java.io.IOException; import java.util.HashSet; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; /** @@ -227,7 +228,7 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu builder.endObject(); } - public static HasParentQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<HasParentQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); float boost = AbstractQueryBuilder.DEFAULT_BOOST; String parentType = null; @@ -238,7 +239,7 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu String currentFieldName = null; XContentParser.Token token; - QueryBuilder iqb = null; + Optional<QueryBuilder> iqb = Optional.empty(); while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); @@ -276,14 +277,18 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu } } } - HasParentQueryBuilder queryBuilder = new HasParentQueryBuilder(parentType, iqb, score) + if (iqb.isPresent() == false) { + // if inner query is empty, bubble this up to caller so they can decide how to deal with it + return Optional.empty(); + } + HasParentQueryBuilder queryBuilder = new HasParentQueryBuilder(parentType, iqb.get(), score) .ignoreUnmapped(ignoreUnmapped) .queryName(queryName) .boost(boost); if (innerHits != null) { queryBuilder.innerHit(innerHits); } - return queryBuilder; + return Optional.of(queryBuilder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/IdsQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/IdsQueryBuilder.java index 7845e2732e..d2c847c55c 100644 --- a/core/src/main/java/org/elasticsearch/index/query/IdsQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/IdsQueryBuilder.java @@ -40,6 +40,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.Set; /** @@ -127,7 +128,7 @@ public class IdsQueryBuilder extends AbstractQueryBuilder<IdsQueryBuilder> { builder.endObject(); } - public static IdsQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<IdsQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); List<String> ids = new ArrayList<>(); List<String> types = new ArrayList<>(); @@ -191,7 +192,7 @@ public class IdsQueryBuilder extends AbstractQueryBuilder<IdsQueryBuilder> { IdsQueryBuilder query = new IdsQueryBuilder(types.toArray(new String[types.size()])); query.addIds(ids.toArray(new String[ids.size()])); query.boost(boost).queryName(queryName); - return query; + return Optional.of(query); } diff --git a/core/src/main/java/org/elasticsearch/index/query/IndicesQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/IndicesQueryBuilder.java index 7cfdf1baa1..9758ad3f54 100644 --- a/core/src/main/java/org/elasticsearch/index/query/IndicesQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/IndicesQueryBuilder.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Objects; +import java.util.Optional; /** * A query that will execute the wrapped query only for the specified indices, @@ -141,7 +142,7 @@ public class IndicesQueryBuilder extends AbstractQueryBuilder<IndicesQueryBuilde builder.endObject(); } - public static IndicesQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException, ParsingException { + public static Optional<IndicesQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException, ParsingException { XContentParser parser = parseContext.parser(); QueryBuilder innerQuery = null; @@ -158,9 +159,10 @@ public class IndicesQueryBuilder extends AbstractQueryBuilder<IndicesQueryBuilde currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { if (parseContext.getParseFieldMatcher().match(currentFieldName, QUERY_FIELD)) { - innerQuery = parseContext.parseInnerQueryBuilder(); + // the 2.0 behaviour when encountering "query" : {} is to return no docs for matching indices + innerQuery = parseContext.parseInnerQueryBuilder().orElse(new MatchNoneQueryBuilder()); } else if (parseContext.getParseFieldMatcher().match(currentFieldName, NO_MATCH_QUERY)) { - noMatchQuery = parseContext.parseInnerQueryBuilder(); + noMatchQuery = parseContext.parseInnerQueryBuilder().orElse(defaultNoMatchQuery()); } else { throw new ParsingException(parser.getTokenLocation(), "[indices] query does not support [" + currentFieldName + "]"); } @@ -203,10 +205,10 @@ public class IndicesQueryBuilder extends AbstractQueryBuilder<IndicesQueryBuilde if (indices.isEmpty()) { throw new ParsingException(parser.getTokenLocation(), "[indices] requires 'indices' or 'index' element"); } - return new IndicesQueryBuilder(innerQuery, indices.toArray(new String[indices.size()])) + return Optional.of(new IndicesQueryBuilder(innerQuery, indices.toArray(new String[indices.size()])) .noMatchQuery(noMatchQuery) .boost(boost) - .queryName(queryName); + .queryName(queryName)); } static QueryBuilder parseNoMatchQuery(String type) { diff --git a/core/src/main/java/org/elasticsearch/index/query/InnerHitBuilder.java b/core/src/main/java/org/elasticsearch/index/query/InnerHitBuilder.java index b62b5a18a1..a017159b45 100644 --- a/core/src/main/java/org/elasticsearch/index/query/InnerHitBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/InnerHitBuilder.java @@ -60,6 +60,7 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl public static final ParseField NAME_FIELD = new ParseField("name"); public static final ParseField INNER_HITS_FIELD = new ParseField("inner_hits"); + public static final QueryBuilder DEFAULT_INNER_HIT_QUERY = new MatchAllQueryBuilder(); private final static ObjectParser<InnerHitBuilder, QueryParseContext> PARSER = new ObjectParser<>("inner_hits", InnerHitBuilder::new); @@ -131,7 +132,7 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl private boolean trackScores; private List<String> fieldNames; - private QueryBuilder query = new MatchAllQueryBuilder(); + private QueryBuilder query = DEFAULT_INNER_HIT_QUERY; private List<SortBuilder<?>> sorts; private List<String> fieldDataFields; private Set<ScriptField> scriptFields; @@ -394,7 +395,7 @@ public final class InnerHitBuilder extends ToXContentToBytes implements Writeabl return this; } - public InnerHitBuilder addSort(SortBuilder sort) { + public InnerHitBuilder addSort(SortBuilder<?> sort) { if (sorts == null) { sorts = new ArrayList<>(); } diff --git a/core/src/main/java/org/elasticsearch/index/query/MatchAllQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/MatchAllQueryBuilder.java index 2d415c2b2a..21742eb877 100644 --- a/core/src/main/java/org/elasticsearch/index/query/MatchAllQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/MatchAllQueryBuilder.java @@ -29,6 +29,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; +import java.util.Optional; /** * A query that matches on all documents. @@ -60,7 +61,7 @@ public class MatchAllQueryBuilder extends AbstractQueryBuilder<MatchAllQueryBuil builder.endObject(); } - public static MatchAllQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<MatchAllQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String currentFieldName = null; @@ -87,7 +88,7 @@ public class MatchAllQueryBuilder extends AbstractQueryBuilder<MatchAllQueryBuil MatchAllQueryBuilder queryBuilder = new MatchAllQueryBuilder(); queryBuilder.boost(boost); queryBuilder.queryName(queryName); - return queryBuilder; + return Optional.of(queryBuilder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/MatchNoneQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/MatchNoneQueryBuilder.java index 068b0e86d8..f96c6160ee 100644 --- a/core/src/main/java/org/elasticsearch/index/query/MatchNoneQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/MatchNoneQueryBuilder.java @@ -29,6 +29,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; +import java.util.Optional; /** * A query that matches no document. @@ -60,7 +61,7 @@ public class MatchNoneQueryBuilder extends AbstractQueryBuilder<MatchNoneQueryBu builder.endObject(); } - public static MatchNoneQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<MatchNoneQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String currentFieldName = null; @@ -88,7 +89,7 @@ public class MatchNoneQueryBuilder extends AbstractQueryBuilder<MatchNoneQueryBu MatchNoneQueryBuilder matchNoneQueryBuilder = new MatchNoneQueryBuilder(); matchNoneQueryBuilder.boost(boost); matchNoneQueryBuilder.queryName(queryName); - return matchNoneQueryBuilder; + return Optional.of(matchNoneQueryBuilder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/MatchPhrasePrefixQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/MatchPhrasePrefixQueryBuilder.java index cb20d448f8..002b5e2343 100644 --- a/core/src/main/java/org/elasticsearch/index/query/MatchPhrasePrefixQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/MatchPhrasePrefixQueryBuilder.java @@ -31,6 +31,7 @@ import org.elasticsearch.index.search.MatchQuery; import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * Match query is a query that analyzes the text and constructs a phrase prefix @@ -191,7 +192,7 @@ public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhr return Objects.hash(fieldName, value, analyzer, slop, maxExpansions); } - public static MatchPhrasePrefixQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<MatchPhrasePrefixQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); XContentParser.Token token = parser.nextToken(); @@ -257,6 +258,6 @@ public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhr matchQuery.maxExpansions(maxExpansion); matchQuery.queryName(queryName); matchQuery.boost(boost); - return matchQuery; + return Optional.of(matchQuery); } } diff --git a/core/src/main/java/org/elasticsearch/index/query/MatchPhraseQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/MatchPhraseQueryBuilder.java index 7fef776bbc..2621c2dc50 100644 --- a/core/src/main/java/org/elasticsearch/index/query/MatchPhraseQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/MatchPhraseQueryBuilder.java @@ -27,8 +27,10 @@ import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.search.MatchQuery; + import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * Match query is a query that analyzes the text and constructs a phrase query @@ -161,7 +163,7 @@ public class MatchPhraseQueryBuilder extends AbstractQueryBuilder<MatchPhraseQue return Objects.hash(fieldName, value, analyzer, slop); } - public static MatchPhraseQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<MatchPhraseQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); XContentParser.Token token = parser.nextToken(); @@ -223,6 +225,6 @@ public class MatchPhraseQueryBuilder extends AbstractQueryBuilder<MatchPhraseQue matchQuery.slop(slop); matchQuery.queryName(queryName); matchQuery.boost(boost); - return matchQuery; + return Optional.of(matchQuery); } } diff --git a/core/src/main/java/org/elasticsearch/index/query/MatchQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/MatchQueryBuilder.java index 6c86759065..04fa9120a7 100644 --- a/core/src/main/java/org/elasticsearch/index/query/MatchQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/MatchQueryBuilder.java @@ -38,6 +38,7 @@ import org.elasticsearch.index.search.MatchQuery.ZeroTermsQuery; import java.io.IOException; import java.util.Locale; import java.util.Objects; +import java.util.Optional; /** * Match query is a query that analyzes the text and constructs a query as the @@ -507,7 +508,7 @@ public class MatchQueryBuilder extends AbstractQueryBuilder<MatchQueryBuilder> { return NAME; } - public static MatchQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<MatchQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); XContentParser.Token token = parser.nextToken(); @@ -633,7 +634,7 @@ public class MatchQueryBuilder extends AbstractQueryBuilder<MatchQueryBuilder> { matchQuery.zeroTermsQuery(zeroTermsQuery); matchQuery.queryName(queryName); matchQuery.boost(boost); - return matchQuery; + return Optional.of(matchQuery); } } diff --git a/core/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryBuilder.java index 66f623cbbb..5fa36ec977 100644 --- a/core/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryBuilder.java @@ -805,7 +805,7 @@ public class MoreLikeThisQueryBuilder extends AbstractQueryBuilder<MoreLikeThisQ builder.endObject(); } - public static MoreLikeThisQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<MoreLikeThisQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); // document inputs @@ -955,7 +955,7 @@ public class MoreLikeThisQueryBuilder extends AbstractQueryBuilder<MoreLikeThisQ if (stopWords != null) { moreLikeThisQueryBuilder.stopWords(stopWords); } - return moreLikeThisQueryBuilder; + return Optional.of(moreLikeThisQueryBuilder); } private static void parseLikeField(QueryParseContext parseContext, List<String> texts, List<Item> items) throws IOException { diff --git a/core/src/main/java/org/elasticsearch/index/query/MultiMatchQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/MultiMatchQueryBuilder.java index 032feac919..0d93b1331b 100644 --- a/core/src/main/java/org/elasticsearch/index/query/MultiMatchQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/MultiMatchQueryBuilder.java @@ -43,6 +43,7 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.TreeMap; /** @@ -556,7 +557,7 @@ public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQuery builder.endObject(); } - public static MultiMatchQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<MultiMatchQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); Object value = null; @@ -660,7 +661,7 @@ public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQuery "Fuziness not allowed for type [" + type.parseField.getPreferredName() + "]"); } - return new MultiMatchQueryBuilder(value) + return Optional.of(new MultiMatchQueryBuilder(value) .fields(fieldsBoosts) .type(type) .analyzer(analyzer) @@ -677,7 +678,7 @@ public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQuery .tieBreaker(tieBreaker) .zeroTermsQuery(zeroTermsQuery) .boost(boost) - .queryName(queryName); + .queryName(queryName)); } private static void parseFieldAndBoost(XContentParser parser, Map<String, Float> fieldsBoosts) throws IOException { diff --git a/core/src/main/java/org/elasticsearch/index/query/NestedQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/NestedQueryBuilder.java index 5d74b54011..1d0e6d11f5 100644 --- a/core/src/main/java/org/elasticsearch/index/query/NestedQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/NestedQueryBuilder.java @@ -36,6 +36,7 @@ import org.elasticsearch.index.mapper.object.ObjectMapper; import java.io.IOException; import java.util.Map; import java.util.Objects; +import java.util.Optional; public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder> { @@ -156,12 +157,12 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder> builder.endObject(); } - public static NestedQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<NestedQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); float boost = AbstractQueryBuilder.DEFAULT_BOOST; ScoreMode scoreMode = ScoreMode.Avg; String queryName = null; - QueryBuilder query = null; + Optional<QueryBuilder> query = Optional.empty(); String path = null; String currentFieldName = null; InnerHitBuilder innerHitBuilder = null; @@ -194,14 +195,19 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder> } } } - NestedQueryBuilder queryBuilder = new NestedQueryBuilder(path, query, scoreMode) + + if (query.isPresent() == false) { + // if inner query is empty, bubble this up to caller so they can decide how to deal with it + return Optional.empty(); + } + NestedQueryBuilder queryBuilder = new NestedQueryBuilder(path, query.get(), scoreMode) .ignoreUnmapped(ignoreUnmapped) .queryName(queryName) .boost(boost); if (innerHitBuilder != null) { queryBuilder.innerHit(innerHitBuilder); } - return queryBuilder; + return Optional.of(queryBuilder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/ParentIdQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/ParentIdQueryBuilder.java index 419149ce99..ede449cbd3 100644 --- a/core/src/main/java/org/elasticsearch/index/query/ParentIdQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/ParentIdQueryBuilder.java @@ -38,6 +38,7 @@ import org.elasticsearch.index.mapper.internal.TypeFieldMapper; import java.io.IOException; import java.util.Objects; +import java.util.Optional; public final class ParentIdQueryBuilder extends AbstractQueryBuilder<ParentIdQueryBuilder> { @@ -117,7 +118,7 @@ public final class ParentIdQueryBuilder extends AbstractQueryBuilder<ParentIdQue builder.endObject(); } - public static ParentIdQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<ParentIdQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); float boost = AbstractQueryBuilder.DEFAULT_BOOST; String type = null; @@ -151,7 +152,7 @@ public final class ParentIdQueryBuilder extends AbstractQueryBuilder<ParentIdQue queryBuilder.queryName(queryName); queryBuilder.boost(boost); queryBuilder.ignoreUnmapped(ignoreUnmapped); - return queryBuilder; + return Optional.of(queryBuilder); } diff --git a/core/src/main/java/org/elasticsearch/index/query/PrefixQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/PrefixQueryBuilder.java index 44677d1840..f92e1d521d 100644 --- a/core/src/main/java/org/elasticsearch/index/query/PrefixQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/PrefixQueryBuilder.java @@ -36,6 +36,7 @@ import org.elasticsearch.index.query.support.QueryParsers; import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * A Query that matches documents containing terms with a specified prefix. @@ -118,7 +119,7 @@ public class PrefixQueryBuilder extends AbstractQueryBuilder<PrefixQueryBuilder> builder.endObject(); } - public static PrefixQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<PrefixQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String fieldName = parser.currentName(); @@ -163,10 +164,10 @@ public class PrefixQueryBuilder extends AbstractQueryBuilder<PrefixQueryBuilder> if (value == null) { throw new ParsingException(parser.getTokenLocation(), "No value specified for prefix query"); } - return new PrefixQueryBuilder(fieldName, value) + return Optional.of(new PrefixQueryBuilder(fieldName, value) .rewrite(rewrite) .boost(boost) - .queryName(queryName); + .queryName(queryName)); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/QueryParseContext.java b/core/src/main/java/org/elasticsearch/index/query/QueryParseContext.java index 62662914fd..93bd07c7bf 100644 --- a/core/src/main/java/org/elasticsearch/index/query/QueryParseContext.java +++ b/core/src/main/java/org/elasticsearch/index/query/QueryParseContext.java @@ -23,14 +23,19 @@ import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.ParseFieldMatcherSupplier; import org.elasticsearch.common.ParsingException; +import org.elasticsearch.common.logging.DeprecationLogger; +import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.indices.query.IndicesQueriesRegistry; import java.io.IOException; import java.util.Objects; +import java.util.Optional; public class QueryParseContext implements ParseFieldMatcherSupplier { + private static final DeprecationLogger DEPRECATION_LOGGER = new DeprecationLogger(Loggers.getLogger(QueryParseContext.class)); + private static final ParseField CACHE = new ParseField("_cache").withAllDeprecated("Elasticsearch makes its own caching decisions"); private static final ParseField CACHE_KEY = new ParseField("_cache_key").withAllDeprecated("Filters are always used as cache keys"); @@ -62,7 +67,7 @@ public class QueryParseContext implements ParseFieldMatcherSupplier { if (token == XContentParser.Token.FIELD_NAME) { String fieldName = parser.currentName(); if ("query".equals(fieldName)) { - queryBuilder = parseInnerQueryBuilder(); + queryBuilder = parseInnerQueryBuilder().orElse(null); } else { throw new ParsingException(parser.getTokenLocation(), "request does not support [" + parser.currentName() + "]"); } @@ -82,7 +87,7 @@ public class QueryParseContext implements ParseFieldMatcherSupplier { /** * Parses a query excluding the query element that wraps it */ - public QueryBuilder parseInnerQueryBuilder() throws IOException { + public Optional<QueryBuilder> parseInnerQueryBuilder() throws IOException { // move to START object XContentParser.Token token; if (parser.currentToken() != XContentParser.Token.START_OBJECT) { @@ -93,8 +98,13 @@ public class QueryParseContext implements ParseFieldMatcherSupplier { } token = parser.nextToken(); if (token == XContentParser.Token.END_OBJECT) { - // empty query - return new EmptyQueryBuilder(); + // we encountered '{}' for a query clause + String msg = "query malformed, empty clause found at [" + parser.getTokenLocation() +"]"; + DEPRECATION_LOGGER.deprecated(msg); + if (parseFieldMatcher.isStrict()) { + throw new IllegalArgumentException(msg); + } + return Optional.empty(); } if (token != XContentParser.Token.FIELD_NAME) { throw new ParsingException(parser.getTokenLocation(), "[_na] query malformed, no field after start_object"); @@ -105,7 +115,9 @@ public class QueryParseContext implements ParseFieldMatcherSupplier { if (token != XContentParser.Token.START_OBJECT && token != XContentParser.Token.START_ARRAY) { throw new ParsingException(parser.getTokenLocation(), "[_na] query malformed, no field after start_object"); } - QueryBuilder result = indicesQueriesRegistry.lookup(queryName, parseFieldMatcher, parser.getTokenLocation()).fromXContent(this); + @SuppressWarnings("unchecked") + Optional<QueryBuilder> result = (Optional<QueryBuilder>) indicesQueriesRegistry.lookup(queryName, parseFieldMatcher, + parser.getTokenLocation()).fromXContent(this); if (parser.currentToken() == XContentParser.Token.END_OBJECT || parser.currentToken() == XContentParser.Token.END_ARRAY) { // if we are at END_OBJECT, move to the next one... parser.nextToken(); diff --git a/core/src/main/java/org/elasticsearch/index/query/QueryParser.java b/core/src/main/java/org/elasticsearch/index/query/QueryParser.java index 069dc86cf8..222d3bd496 100644 --- a/core/src/main/java/org/elasticsearch/index/query/QueryParser.java +++ b/core/src/main/java/org/elasticsearch/index/query/QueryParser.java @@ -20,6 +20,7 @@ package org.elasticsearch.index.query; import java.io.IOException; +import java.util.Optional; /** * Defines a query parser that is able to parse {@link QueryBuilder}s from {@link org.elasticsearch.common.xcontent.XContent}. @@ -36,5 +37,12 @@ public interface QueryParser<QB extends QueryBuilder> { * call * @return the new QueryBuilder */ - QB fromXContent(QueryParseContext parseContext) throws IOException; + Optional<QB> fromXContent(QueryParseContext parseContext) throws IOException; + + /** + * @return an empty {@link QueryBuilder} instance for this parser that can be used for deserialization + */ + default QB getBuilderPrototype() { // TODO remove this when nothing implements it + throw new UnsupportedOperationException(); + } } diff --git a/core/src/main/java/org/elasticsearch/index/query/QueryStringQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/QueryStringQueryBuilder.java index 6806ae944c..c390507a78 100644 --- a/core/src/main/java/org/elasticsearch/index/query/QueryStringQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/QueryStringQueryBuilder.java @@ -46,6 +46,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.TreeMap; /** @@ -631,7 +632,7 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue builder.endObject(); } - public static QueryStringQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<QueryStringQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String currentFieldName = null; XContentParser.Token token; @@ -792,7 +793,7 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue queryStringQuery.locale(locale); queryStringQuery.boost(boost); queryStringQuery.queryName(queryName); - return queryStringQuery; + return Optional.of(queryStringQuery); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/RangeQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/RangeQueryBuilder.java index 241c38475a..1c51b6a2dd 100644 --- a/core/src/main/java/org/elasticsearch/index/query/RangeQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/RangeQueryBuilder.java @@ -42,6 +42,7 @@ import org.joda.time.DateTimeZone; import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * A Query that matches documents within an range of terms. @@ -297,7 +298,7 @@ public class RangeQueryBuilder extends AbstractQueryBuilder<RangeQueryBuilder> i builder.endObject(); } - public static RangeQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<RangeQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String fieldName = null; @@ -381,7 +382,7 @@ public class RangeQueryBuilder extends AbstractQueryBuilder<RangeQueryBuilder> i if (format != null) { rangeQuery.format(format); } - return rangeQuery; + return Optional.of(rangeQuery); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/RegexpQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/RegexpQueryBuilder.java index 703b2463b1..27462cfb26 100644 --- a/core/src/main/java/org/elasticsearch/index/query/RegexpQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/RegexpQueryBuilder.java @@ -37,6 +37,7 @@ import org.elasticsearch.index.query.support.QueryParsers; import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * A Query that does fuzzy matching for a specific value. @@ -179,7 +180,7 @@ public class RegexpQueryBuilder extends AbstractQueryBuilder<RegexpQueryBuilder> builder.endObject(); } - public static RegexpQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<RegexpQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String fieldName = parser.currentName(); @@ -237,12 +238,12 @@ public class RegexpQueryBuilder extends AbstractQueryBuilder<RegexpQueryBuilder> if (value == null) { throw new ParsingException(parser.getTokenLocation(), "No value specified for regexp query"); } - return new RegexpQueryBuilder(fieldName, value) + return Optional.of(new RegexpQueryBuilder(fieldName, value) .flags(flagsValue) .maxDeterminizedStates(maxDeterminizedStates) .rewrite(rewrite) .boost(boost) - .queryName(queryName); + .queryName(queryName)); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/ScriptQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/ScriptQueryBuilder.java index 12aba8ae87..6d563f22a0 100644 --- a/core/src/main/java/org/elasticsearch/index/query/ScriptQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/ScriptQueryBuilder.java @@ -35,9 +35,9 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.script.LeafSearchScript; import org.elasticsearch.script.Script; import org.elasticsearch.script.Script.ScriptField; -import org.elasticsearch.script.ScriptParameterParser.ScriptParameterValue; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptParameterParser; +import org.elasticsearch.script.ScriptParameterParser.ScriptParameterValue; import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.SearchScript; import org.elasticsearch.search.lookup.SearchLookup; @@ -47,6 +47,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Optional; public class ScriptQueryBuilder extends AbstractQueryBuilder<ScriptQueryBuilder> { @@ -94,7 +95,7 @@ public class ScriptQueryBuilder extends AbstractQueryBuilder<ScriptQueryBuilder> builder.endObject(); } - public static ScriptQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<ScriptQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); ScriptParameterParser scriptParameterParser = new ScriptParameterParser(); @@ -149,9 +150,9 @@ public class ScriptQueryBuilder extends AbstractQueryBuilder<ScriptQueryBuilder> throw new ParsingException(parser.getTokenLocation(), "script must be provided with a [script] filter"); } - return new ScriptQueryBuilder(script) + return Optional.of(new ScriptQueryBuilder(script) .boost(boost) - .queryName(queryName); + .queryName(queryName)); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/SimpleQueryStringBuilder.java b/core/src/main/java/org/elasticsearch/index/query/SimpleQueryStringBuilder.java index 5e2c88af92..0bedf67820 100644 --- a/core/src/main/java/org/elasticsearch/index/query/SimpleQueryStringBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/SimpleQueryStringBuilder.java @@ -39,6 +39,7 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.TreeMap; /** @@ -417,7 +418,7 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt builder.endObject(); } - public static SimpleQueryStringBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<SimpleQueryStringBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String currentFieldName = null; @@ -514,7 +515,7 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt qb.boost(boost).fields(fieldsAndWeights).analyzer(analyzerName).queryName(queryName).minimumShouldMatch(minimumShouldMatch); qb.flags(flags).defaultOperator(defaultOperator).locale(locale).lowercaseExpandedTerms(lowercaseExpandedTerms); qb.lenient(lenient).analyzeWildcard(analyzeWildcard).boost(boost); - return qb; + return Optional.of(qb); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/SpanContainingQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/SpanContainingQueryBuilder.java index ae4297e431..5d22df1557 100644 --- a/core/src/main/java/org/elasticsearch/index/query/SpanContainingQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/SpanContainingQueryBuilder.java @@ -31,6 +31,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * Builder for {@link org.apache.lucene.search.spans.SpanContainingQuery}. @@ -102,7 +103,7 @@ public class SpanContainingQueryBuilder extends AbstractQueryBuilder<SpanContain builder.endObject(); } - public static SpanContainingQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<SpanContainingQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); float boost = AbstractQueryBuilder.DEFAULT_BOOST; String queryName = null; @@ -116,17 +117,17 @@ public class SpanContainingQueryBuilder extends AbstractQueryBuilder<SpanContain currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { if (parseContext.getParseFieldMatcher().match(currentFieldName, BIG_FIELD)) { - QueryBuilder query = parseContext.parseInnerQueryBuilder(); - if (!(query instanceof SpanQueryBuilder)) { + Optional<QueryBuilder> query = parseContext.parseInnerQueryBuilder(); + if (query.isPresent() == false || query.get() instanceof SpanQueryBuilder == false) { throw new ParsingException(parser.getTokenLocation(), "span_containing [big] must be of type span query"); } - big = (SpanQueryBuilder) query; + big = (SpanQueryBuilder) query.get(); } else if (parseContext.getParseFieldMatcher().match(currentFieldName, LITTLE_FIELD)) { - QueryBuilder query = parseContext.parseInnerQueryBuilder(); - if (!(query instanceof SpanQueryBuilder)) { + Optional<QueryBuilder> query = parseContext.parseInnerQueryBuilder(); + if (query.isPresent() == false || query.get() instanceof SpanQueryBuilder == false) { throw new ParsingException(parser.getTokenLocation(), "span_containing [little] must be of type span query"); } - little = (SpanQueryBuilder) query; + little = (SpanQueryBuilder) query.get(); } else { throw new ParsingException(parser.getTokenLocation(), "[span_containing] query does not support [" + currentFieldName + "]"); @@ -143,7 +144,7 @@ public class SpanContainingQueryBuilder extends AbstractQueryBuilder<SpanContain SpanContainingQueryBuilder query = new SpanContainingQueryBuilder(big, little); query.boost(boost).queryName(queryName); - return query; + return Optional.of(query); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/SpanFirstQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/SpanFirstQueryBuilder.java index 009f8a3965..b0b096b19e 100644 --- a/core/src/main/java/org/elasticsearch/index/query/SpanFirstQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/SpanFirstQueryBuilder.java @@ -31,6 +31,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; import java.util.Objects; +import java.util.Optional; public class SpanFirstQueryBuilder extends AbstractQueryBuilder<SpanFirstQueryBuilder> implements SpanQueryBuilder { @@ -101,7 +102,7 @@ public class SpanFirstQueryBuilder extends AbstractQueryBuilder<SpanFirstQueryBu builder.endObject(); } - public static SpanFirstQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<SpanFirstQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); float boost = AbstractQueryBuilder.DEFAULT_BOOST; @@ -117,11 +118,11 @@ public class SpanFirstQueryBuilder extends AbstractQueryBuilder<SpanFirstQueryBu currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { if (parseContext.getParseFieldMatcher().match(currentFieldName, MATCH_FIELD)) { - QueryBuilder query = parseContext.parseInnerQueryBuilder(); - if (!(query instanceof SpanQueryBuilder)) { + Optional<QueryBuilder> query = parseContext.parseInnerQueryBuilder(); + if (query.isPresent() == false || query.get() instanceof SpanQueryBuilder == false) { throw new ParsingException(parser.getTokenLocation(), "spanFirst [match] must be of type span query"); } - match = (SpanQueryBuilder) query; + match = (SpanQueryBuilder) query.get(); } else { throw new ParsingException(parser.getTokenLocation(), "[span_first] query does not support [" + currentFieldName + "]"); } @@ -145,7 +146,7 @@ public class SpanFirstQueryBuilder extends AbstractQueryBuilder<SpanFirstQueryBu } SpanFirstQueryBuilder queryBuilder = new SpanFirstQueryBuilder(match, end); queryBuilder.boost(boost).queryName(queryName); - return queryBuilder; + return Optional.of(queryBuilder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/SpanMultiTermQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/SpanMultiTermQueryBuilder.java index 86418903f7..0849d1c6a6 100644 --- a/core/src/main/java/org/elasticsearch/index/query/SpanMultiTermQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/SpanMultiTermQueryBuilder.java @@ -33,6 +33,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * Query that allows wraping a {@link MultiTermQueryBuilder} (one of wildcard, fuzzy, prefix, term, range or regexp query) @@ -82,7 +83,7 @@ public class SpanMultiTermQueryBuilder extends AbstractQueryBuilder<SpanMultiTer builder.endObject(); } - public static SpanMultiTermQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<SpanMultiTermQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String currentFieldName = null; MultiTermQueryBuilder subQuery = null; @@ -94,12 +95,12 @@ public class SpanMultiTermQueryBuilder extends AbstractQueryBuilder<SpanMultiTer currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { if (parseContext.getParseFieldMatcher().match(currentFieldName, MATCH_FIELD)) { - QueryBuilder innerQuery = parseContext.parseInnerQueryBuilder(); - if (innerQuery instanceof MultiTermQueryBuilder == false) { + Optional<QueryBuilder> query = parseContext.parseInnerQueryBuilder(); + if (query.isPresent() == false || query.get() instanceof MultiTermQueryBuilder == false) { throw new ParsingException(parser.getTokenLocation(), "[span_multi] [" + MATCH_FIELD.getPreferredName() + "] must be of type multi term query"); } - subQuery = (MultiTermQueryBuilder) innerQuery; + subQuery = (MultiTermQueryBuilder) query.get(); } else { throw new ParsingException(parser.getTokenLocation(), "[span_multi] query does not support [" + currentFieldName + "]"); } @@ -119,7 +120,7 @@ public class SpanMultiTermQueryBuilder extends AbstractQueryBuilder<SpanMultiTer "[span_multi] must have [" + MATCH_FIELD.getPreferredName() + "] multi term query clause"); } - return new SpanMultiTermQueryBuilder(subQuery).queryName(queryName).boost(boost); + return Optional.of(new SpanMultiTermQueryBuilder(subQuery).queryName(queryName).boost(boost)); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/SpanNearQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/SpanNearQueryBuilder.java index cebc72c077..c11164ae7a 100644 --- a/core/src/main/java/org/elasticsearch/index/query/SpanNearQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/SpanNearQueryBuilder.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.Optional; /** * Matches spans which are near one another. One can specify slop, the maximum number @@ -146,7 +147,7 @@ public class SpanNearQueryBuilder extends AbstractQueryBuilder<SpanNearQueryBuil builder.endObject(); } - public static SpanNearQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<SpanNearQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); float boost = AbstractQueryBuilder.DEFAULT_BOOST; @@ -164,11 +165,11 @@ public class SpanNearQueryBuilder extends AbstractQueryBuilder<SpanNearQueryBuil } else if (token == XContentParser.Token.START_ARRAY) { if (parseContext.getParseFieldMatcher().match(currentFieldName, CLAUSES_FIELD)) { while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { - QueryBuilder query = parseContext.parseInnerQueryBuilder(); - if (!(query instanceof SpanQueryBuilder)) { + Optional<QueryBuilder> query = parseContext.parseInnerQueryBuilder(); + if (query.isPresent() == false || query.get() instanceof SpanQueryBuilder == false) { throw new ParsingException(parser.getTokenLocation(), "spanNear [clauses] must be of type span query"); } - clauses.add((SpanQueryBuilder) query); + clauses.add((SpanQueryBuilder) query.get()); } } else { throw new ParsingException(parser.getTokenLocation(), "[span_near] query does not support [" + currentFieldName + "]"); @@ -207,7 +208,7 @@ public class SpanNearQueryBuilder extends AbstractQueryBuilder<SpanNearQueryBuil queryBuilder.inOrder(inOrder); queryBuilder.boost(boost); queryBuilder.queryName(queryName); - return queryBuilder; + return Optional.of(queryBuilder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/SpanNotQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/SpanNotQueryBuilder.java index 02ce431de1..6bb635b200 100644 --- a/core/src/main/java/org/elasticsearch/index/query/SpanNotQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/SpanNotQueryBuilder.java @@ -31,6 +31,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; import java.util.Objects; +import java.util.Optional; public class SpanNotQueryBuilder extends AbstractQueryBuilder<SpanNotQueryBuilder> implements SpanQueryBuilder { @@ -162,7 +163,7 @@ public class SpanNotQueryBuilder extends AbstractQueryBuilder<SpanNotQueryBuilde builder.endObject(); } - public static SpanNotQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<SpanNotQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); float boost = AbstractQueryBuilder.DEFAULT_BOOST; @@ -183,17 +184,17 @@ public class SpanNotQueryBuilder extends AbstractQueryBuilder<SpanNotQueryBuilde currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { if (parseContext.getParseFieldMatcher().match(currentFieldName, INCLUDE_FIELD)) { - QueryBuilder query = parseContext.parseInnerQueryBuilder(); - if (!(query instanceof SpanQueryBuilder)) { + Optional<QueryBuilder> query = parseContext.parseInnerQueryBuilder(); + if (query.isPresent() == false || query.get() instanceof SpanQueryBuilder == false) { throw new ParsingException(parser.getTokenLocation(), "spanNot [include] must be of type span query"); } - include = (SpanQueryBuilder) query; + include = (SpanQueryBuilder) query.get(); } else if (parseContext.getParseFieldMatcher().match(currentFieldName, EXCLUDE_FIELD)) { - QueryBuilder query = parseContext.parseInnerQueryBuilder(); - if (!(query instanceof SpanQueryBuilder)) { + Optional<QueryBuilder> query = parseContext.parseInnerQueryBuilder(); + if (query.isPresent() == false || query.get() instanceof SpanQueryBuilder == false) { throw new ParsingException(parser.getTokenLocation(), "spanNot [exclude] must be of type span query"); } - exclude = (SpanQueryBuilder) query; + exclude = (SpanQueryBuilder) query.get(); } else { throw new ParsingException(parser.getTokenLocation(), "[span_not] query does not support [" + currentFieldName + "]"); } @@ -235,7 +236,7 @@ public class SpanNotQueryBuilder extends AbstractQueryBuilder<SpanNotQueryBuilde } spanNotQuery.boost(boost); spanNotQuery.queryName(queryName); - return spanNotQuery; + return Optional.of(spanNotQuery); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/SpanOrQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/SpanOrQueryBuilder.java index 98698307d0..5169e0d933 100644 --- a/core/src/main/java/org/elasticsearch/index/query/SpanOrQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/SpanOrQueryBuilder.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.Optional; /** * Span query that matches the union of its clauses. Maps to {@link SpanOrQuery}. @@ -99,7 +100,7 @@ public class SpanOrQueryBuilder extends AbstractQueryBuilder<SpanOrQueryBuilder> builder.endObject(); } - public static SpanOrQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<SpanOrQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); float boost = AbstractQueryBuilder.DEFAULT_BOOST; @@ -115,11 +116,11 @@ public class SpanOrQueryBuilder extends AbstractQueryBuilder<SpanOrQueryBuilder> } else if (token == XContentParser.Token.START_ARRAY) { if (parseContext.getParseFieldMatcher().match(currentFieldName, CLAUSES_FIELD)) { while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { - QueryBuilder query = parseContext.parseInnerQueryBuilder(); - if (!(query instanceof SpanQueryBuilder)) { + Optional<QueryBuilder> query = parseContext.parseInnerQueryBuilder(); + if (query.isPresent() == false || query.get() instanceof SpanQueryBuilder == false) { throw new ParsingException(parser.getTokenLocation(), "spanOr [clauses] must be of type span query"); } - clauses.add((SpanQueryBuilder) query); + clauses.add((SpanQueryBuilder) query.get()); } } else { throw new ParsingException(parser.getTokenLocation(), "[span_or] query does not support [" + currentFieldName + "]"); @@ -145,7 +146,7 @@ public class SpanOrQueryBuilder extends AbstractQueryBuilder<SpanOrQueryBuilder> } queryBuilder.boost(boost); queryBuilder.queryName(queryName); - return queryBuilder; + return Optional.of(queryBuilder); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/SpanTermQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/SpanTermQueryBuilder.java index 3bb374ff27..56581c3991 100644 --- a/core/src/main/java/org/elasticsearch/index/query/SpanTermQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/SpanTermQueryBuilder.java @@ -31,6 +31,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.mapper.MappedFieldType; import java.io.IOException; +import java.util.Optional; /** * A Span Query that matches documents containing a term. @@ -93,7 +94,7 @@ public class SpanTermQueryBuilder extends BaseTermQueryBuilder<SpanTermQueryBuil return new SpanTermQuery(term); } - public static SpanTermQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException, ParsingException { + public static Optional<SpanTermQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException, ParsingException { XContentParser parser = parseContext.parser(); XContentParser.Token token = parser.currentToken(); @@ -142,7 +143,7 @@ public class SpanTermQueryBuilder extends BaseTermQueryBuilder<SpanTermQueryBuil SpanTermQueryBuilder result = new SpanTermQueryBuilder(fieldName, value); result.boost(boost).queryName(queryName); - return result; + return Optional.of(result); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/SpanWithinQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/SpanWithinQueryBuilder.java index eaedc80bab..2975063f78 100644 --- a/core/src/main/java/org/elasticsearch/index/query/SpanWithinQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/SpanWithinQueryBuilder.java @@ -31,6 +31,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * Builder for {@link org.apache.lucene.search.spans.SpanWithinQuery}. @@ -107,7 +108,7 @@ public class SpanWithinQueryBuilder extends AbstractQueryBuilder<SpanWithinQuery builder.endObject(); } - public static SpanWithinQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<SpanWithinQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); float boost = AbstractQueryBuilder.DEFAULT_BOOST; @@ -122,17 +123,17 @@ public class SpanWithinQueryBuilder extends AbstractQueryBuilder<SpanWithinQuery currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { if (parseContext.getParseFieldMatcher().match(currentFieldName, BIG_FIELD)) { - QueryBuilder query = parseContext.parseInnerQueryBuilder(); - if (query instanceof SpanQueryBuilder == false) { + Optional<QueryBuilder> query = parseContext.parseInnerQueryBuilder(); + if (query.isPresent() == false || query.get() instanceof SpanQueryBuilder == false) { throw new ParsingException(parser.getTokenLocation(), "span_within [big] must be of type span query"); } - big = (SpanQueryBuilder) query; + big = (SpanQueryBuilder) query.get(); } else if (parseContext.getParseFieldMatcher().match(currentFieldName, LITTLE_FIELD)) { - QueryBuilder query = parseContext.parseInnerQueryBuilder(); - if (query instanceof SpanQueryBuilder == false) { + Optional<QueryBuilder> query = parseContext.parseInnerQueryBuilder(); + if (query.isPresent() == false || query.get() instanceof SpanQueryBuilder == false) { throw new ParsingException(parser.getTokenLocation(), "span_within [little] must be of type span query"); } - little = (SpanQueryBuilder) query; + little = (SpanQueryBuilder) query.get(); } else { throw new ParsingException(parser.getTokenLocation(), "[span_within] query does not support [" + currentFieldName + "]"); @@ -155,7 +156,7 @@ public class SpanWithinQueryBuilder extends AbstractQueryBuilder<SpanWithinQuery SpanWithinQueryBuilder query = new SpanWithinQueryBuilder(big, little); query.boost(boost).queryName(queryName); - return query; + return Optional.of(query); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/TemplateQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/TemplateQueryBuilder.java index 1a4d05374b..3b41abbbe8 100644 --- a/core/src/main/java/org/elasticsearch/index/query/TemplateQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/TemplateQueryBuilder.java @@ -21,6 +21,7 @@ package org.elasticsearch.index.query; import org.apache.lucene.search.Query; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseFieldMatcher; +import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -37,6 +38,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Optional; /** * Facilitates creating template query requests. @@ -120,10 +122,10 @@ public class TemplateQueryBuilder extends AbstractQueryBuilder<TemplateQueryBuil * In the simplest case, parse template string and variables from the request, * compile the template and execute the template against the given variables. */ - public static TemplateQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<TemplateQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); Template template = parse(parser, parseContext.getParseFieldMatcher()); - return new TemplateQueryBuilder(template); + return Optional.of(new TemplateQueryBuilder(template)); } public static Template parse(XContentParser parser, ParseFieldMatcher parseFieldMatcher, String... parameters) throws IOException { @@ -179,7 +181,8 @@ public class TemplateQueryBuilder extends AbstractQueryBuilder<TemplateQueryBuil BytesReference querySource = (BytesReference) executable.run(); try (XContentParser qSourceParser = XContentFactory.xContent(querySource).createParser(querySource)) { final QueryParseContext queryParseContext = queryRewriteContext.newParseContext(qSourceParser); - final QueryBuilder queryBuilder = queryParseContext.parseInnerQueryBuilder(); + final QueryBuilder queryBuilder = queryParseContext.parseInnerQueryBuilder().orElseThrow( + () -> new ParsingException(qSourceParser.getTokenLocation(), "inner query in [" + NAME + "] cannot be empty"));; if (boost() != DEFAULT_BOOST || queryName() != null) { final BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); boolQueryBuilder.must(queryBuilder); diff --git a/core/src/main/java/org/elasticsearch/index/query/TermQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/TermQueryBuilder.java index ffdf6a3337..bfb55c9956 100644 --- a/core/src/main/java/org/elasticsearch/index/query/TermQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/TermQueryBuilder.java @@ -30,6 +30,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.mapper.MappedFieldType; import java.io.IOException; +import java.util.Optional; /** * A Query that matches documents containing a term. @@ -84,7 +85,7 @@ public class TermQueryBuilder extends BaseTermQueryBuilder<TermQueryBuilder> { super(in); } - public static TermQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<TermQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String queryName = null; @@ -140,7 +141,7 @@ public class TermQueryBuilder extends BaseTermQueryBuilder<TermQueryBuilder> { if (queryName != null) { termQuery.queryName(queryName); } - return termQuery; + return Optional.of(termQuery); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java index 5b0650eb7e..7d27a911f8 100644 --- a/core/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java @@ -47,6 +47,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -238,7 +239,7 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> { builder.endObject(); } - public static TermsQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<TermsQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); String fieldName = null; @@ -289,9 +290,9 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> { throw new ParsingException(parser.getTokenLocation(), "[" + TermsQueryBuilder.NAME + "] query requires a field name, " + "followed by array of terms or a document lookup specification"); } - return new TermsQueryBuilder(fieldName, values, termsLookup) + return Optional.of(new TermsQueryBuilder(fieldName, values, termsLookup) .boost(boost) - .queryName(queryName); + .queryName(queryName)); } private static List<Object> parseValues(XContentParser parser) throws IOException { diff --git a/core/src/main/java/org/elasticsearch/index/query/TypeQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/TypeQueryBuilder.java index 129b027552..00cd108c00 100644 --- a/core/src/main/java/org/elasticsearch/index/query/TypeQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/TypeQueryBuilder.java @@ -33,6 +33,7 @@ import org.elasticsearch.index.mapper.DocumentMapper; import java.io.IOException; import java.util.Objects; +import java.util.Optional; public class TypeQueryBuilder extends AbstractQueryBuilder<TypeQueryBuilder> { public static final String NAME = "type"; @@ -81,7 +82,7 @@ public class TypeQueryBuilder extends AbstractQueryBuilder<TypeQueryBuilder> { builder.endObject(); } - public static TypeQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<TypeQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); BytesRef type = null; @@ -114,9 +115,9 @@ public class TypeQueryBuilder extends AbstractQueryBuilder<TypeQueryBuilder> { throw new ParsingException(parser.getTokenLocation(), "[" + TypeQueryBuilder.NAME + "] filter needs to be provided with a value for the type"); } - return new TypeQueryBuilder(type) + return Optional.of(new TypeQueryBuilder(type) .boost(boost) - .queryName(queryName); + .queryName(queryName)); } diff --git a/core/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java index ef49472b8c..007dff9234 100644 --- a/core/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java @@ -36,6 +36,7 @@ import org.elasticsearch.index.query.support.QueryParsers; import java.io.IOException; import java.util.Objects; +import java.util.Optional; /** * Implements the wildcard search query. Supported wildcards are <tt>*</tt>, which @@ -135,7 +136,7 @@ public class WildcardQueryBuilder extends AbstractQueryBuilder<WildcardQueryBuil builder.endObject(); } - public static WildcardQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<WildcardQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); XContentParser.Token token = parser.nextToken(); @@ -180,10 +181,10 @@ public class WildcardQueryBuilder extends AbstractQueryBuilder<WildcardQueryBuil if (value == null) { throw new ParsingException(parser.getTokenLocation(), "No value specified for wildcard query"); } - return new WildcardQueryBuilder(fieldName, value) + return Optional.of(new WildcardQueryBuilder(fieldName, value) .rewrite(rewrite) .boost(boost) - .queryName(queryName); + .queryName(queryName)); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/query/WrapperQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/WrapperQueryBuilder.java index 4037666393..4e1eb83272 100644 --- a/core/src/main/java/org/elasticsearch/index/query/WrapperQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/WrapperQueryBuilder.java @@ -33,6 +33,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.Optional; /** * A Query builder which allows building a query given JSON string or binary data provided as input. This is useful when you want @@ -116,7 +117,7 @@ public class WrapperQueryBuilder extends AbstractQueryBuilder<WrapperQueryBuilde builder.endObject(); } - public static WrapperQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + public static Optional<WrapperQueryBuilder> fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); XContentParser.Token token = parser.nextToken(); @@ -136,7 +137,7 @@ public class WrapperQueryBuilder extends AbstractQueryBuilder<WrapperQueryBuilde if (source == null) { throw new ParsingException(parser.getTokenLocation(), "wrapper query has no [query] specified"); } - return new WrapperQueryBuilder(source); + return Optional.of(new WrapperQueryBuilder(source)); } @Override @@ -164,7 +165,8 @@ public class WrapperQueryBuilder extends AbstractQueryBuilder<WrapperQueryBuilde try (XContentParser qSourceParser = XContentFactory.xContent(source).createParser(source)) { QueryParseContext parseContext = context.newParseContext(qSourceParser); - final QueryBuilder queryBuilder = parseContext.parseInnerQueryBuilder(); + final QueryBuilder queryBuilder = parseContext.parseInnerQueryBuilder().orElseThrow( + () -> new ParsingException(qSourceParser.getTokenLocation(), "inner query cannot be empty")); if (boost() != DEFAULT_BOOST || queryName() != null) { final BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); boolQueryBuilder.must(queryBuilder); diff --git a/core/src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilder.java index 98f878d1c2..3e52322d22 100644 --- a/core/src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/functionscore/FunctionScoreQueryBuilder.java @@ -37,12 +37,13 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentLocation; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.query.AbstractQueryBuilder; +import org.elasticsearch.index.query.InnerHitBuilder; import org.elasticsearch.index.query.MatchAllQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryRewriteContext; import org.elasticsearch.index.query.QueryShardContext; -import org.elasticsearch.index.query.InnerHitBuilder; import java.io.IOException; import java.util.ArrayList; @@ -51,6 +52,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; /** * A query that uses a filters with a script associated with them to compute the @@ -431,15 +433,13 @@ public class FunctionScoreQueryBuilder extends AbstractQueryBuilder<FunctionScor return this; } - - @Override protected void extractInnerHitBuilders(Map<String, InnerHitBuilder> innerHits) { InnerHitBuilder.extractInnerHits(query(), innerHits); } - public static FunctionScoreQueryBuilder fromXContent(ParseFieldRegistry<ScoreFunctionParser<?>> scoreFunctionsRegistry, - QueryParseContext parseContext) throws IOException { + public static Optional<FunctionScoreQueryBuilder> fromXContent(ParseFieldRegistry<ScoreFunctionParser<?>> scoreFunctionsRegistry, + QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); QueryBuilder query = null; @@ -468,7 +468,7 @@ public class FunctionScoreQueryBuilder extends AbstractQueryBuilder<FunctionScor throw new ParsingException(parser.getTokenLocation(), "failed to parse [{}] query. [query] is already defined.", NAME); } - query = parseContext.parseInnerQueryBuilder(); + query = parseContext.parseInnerQueryBuilder().orElse(QueryBuilders.matchAllQuery()); } else { if (singleFunctionFound) { throw new ParsingException(parser.getTokenLocation(), @@ -556,7 +556,7 @@ public class FunctionScoreQueryBuilder extends AbstractQueryBuilder<FunctionScor } functionScoreQueryBuilder.boost(boost); functionScoreQueryBuilder.queryName(queryName); - return functionScoreQueryBuilder; + return Optional.of(functionScoreQueryBuilder); } private static void handleMisplacedFunctionsDeclaration(XContentLocation contentLocation, String errorString) { @@ -584,7 +584,7 @@ public class FunctionScoreQueryBuilder extends AbstractQueryBuilder<FunctionScor currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { if (parseContext.getParseFieldMatcher().match(currentFieldName, FILTER_FIELD)) { - filter = parseContext.parseInnerQueryBuilder(); + filter = parseContext.parseInnerQueryBuilder().orElse(QueryBuilders.matchAllQuery()); } else { if (scoreFunction != null) { throw new ParsingException(parser.getTokenLocation(), |