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 04fa9120a76..64d025adf71 100644 --- a/core/src/main/java/org/elasticsearch/index/query/MatchQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/MatchQueryBuilder.java @@ -510,13 +510,7 @@ public class MatchQueryBuilder extends AbstractQueryBuilder { public static Optional fromXContent(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); - - XContentParser.Token token = parser.nextToken(); - if (token != XContentParser.Token.FIELD_NAME) { - throw new ParsingException(parser.getTokenLocation(), "[" + MatchQueryBuilder.NAME + "] query malformed, no field"); - } - String fieldName = parser.currentName(); - + String fieldName = null; MatchQuery.Type type = MatchQuery.Type.BOOLEAN; Object value = null; float boost = AbstractQueryBuilder.DEFAULT_BOOST; @@ -533,80 +527,84 @@ public class MatchQueryBuilder extends AbstractQueryBuilder { Float cutOffFrequency = null; ZeroTermsQuery zeroTermsQuery = MatchQuery.DEFAULT_ZERO_TERMS_QUERY; String queryName = null; - - token = parser.nextToken(); - if (token == XContentParser.Token.START_OBJECT) { - String currentFieldName = null; - while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { - if (token == XContentParser.Token.FIELD_NAME) { - currentFieldName = parser.currentName(); - } else if (token.isValue()) { - if (parseContext.getParseFieldMatcher().match(currentFieldName, QUERY_FIELD)) { - value = parser.objectText(); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, TYPE_FIELD)) { - String tStr = parser.text(); - if ("boolean".equals(tStr)) { - type = MatchQuery.Type.BOOLEAN; - } else if ("phrase".equals(tStr)) { - type = MatchQuery.Type.PHRASE; - } else if ("phrase_prefix".equals(tStr) || ("phrasePrefix".equals(tStr))) { - type = MatchQuery.Type.PHRASE_PREFIX; - } else { - throw new ParsingException(parser.getTokenLocation(), "[" + NAME + "] query does not support type " + tStr); - } - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, ANALYZER_FIELD)) { - analyzer = parser.text(); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.BOOST_FIELD)) { - boost = parser.floatValue(); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, SLOP_FIELD)) { - slop = parser.intValue(); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, Fuzziness.FIELD)) { - fuzziness = Fuzziness.parse(parser); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, PREFIX_LENGTH_FIELD)) { - prefixLength = parser.intValue(); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, MAX_EXPANSIONS_FIELD)) { - maxExpansion = parser.intValue(); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, OPERATOR_FIELD)) { - operator = Operator.fromString(parser.text()); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, MINIMUM_SHOULD_MATCH_FIELD)) { - minimumShouldMatch = parser.textOrNull(); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, FUZZY_REWRITE_FIELD)) { - fuzzyRewrite = parser.textOrNull(); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, FUZZY_TRANSPOSITIONS_FIELD)) { - fuzzyTranspositions = parser.booleanValue(); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, LENIENT_FIELD)) { - lenient = parser.booleanValue(); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, CUTOFF_FREQUENCY_FIELD)) { - cutOffFrequency = parser.floatValue(); - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, ZERO_TERMS_QUERY_FIELD)) { - String zeroTermsDocs = parser.text(); - if ("none".equalsIgnoreCase(zeroTermsDocs)) { - zeroTermsQuery = MatchQuery.ZeroTermsQuery.NONE; - } else if ("all".equalsIgnoreCase(zeroTermsDocs)) { - zeroTermsQuery = MatchQuery.ZeroTermsQuery.ALL; + String currentFieldName = null; + XContentParser.Token token; + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + currentFieldName = parser.currentName(); + } else if (parseContext.isDeprecatedSetting(currentFieldName)) { + // skip + } else if (token == XContentParser.Token.START_OBJECT) { + if (fieldName != null) { + throw new ParsingException(parser.getTokenLocation(), "[match] query doesn't support multiple fields, found [" + + fieldName + "] and [" + currentFieldName + "]"); + } + fieldName = currentFieldName; + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + currentFieldName = parser.currentName(); + } else if (token.isValue()) { + if (parseContext.getParseFieldMatcher().match(currentFieldName, QUERY_FIELD)) { + value = parser.objectText(); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, TYPE_FIELD)) { + String tStr = parser.text(); + if ("boolean".equals(tStr)) { + type = MatchQuery.Type.BOOLEAN; + } else if ("phrase".equals(tStr)) { + type = MatchQuery.Type.PHRASE; + } else if ("phrase_prefix".equals(tStr) || ("phrasePrefix".equals(tStr))) { + type = MatchQuery.Type.PHRASE_PREFIX; + } else { + throw new ParsingException(parser.getTokenLocation(), "[" + NAME + "] query does not support type " + tStr); + } + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, ANALYZER_FIELD)) { + analyzer = parser.text(); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.BOOST_FIELD)) { + boost = parser.floatValue(); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, SLOP_FIELD)) { + slop = parser.intValue(); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, Fuzziness.FIELD)) { + fuzziness = Fuzziness.parse(parser); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, PREFIX_LENGTH_FIELD)) { + prefixLength = parser.intValue(); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, MAX_EXPANSIONS_FIELD)) { + maxExpansion = parser.intValue(); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, OPERATOR_FIELD)) { + operator = Operator.fromString(parser.text()); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, MINIMUM_SHOULD_MATCH_FIELD)) { + minimumShouldMatch = parser.textOrNull(); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, FUZZY_REWRITE_FIELD)) { + fuzzyRewrite = parser.textOrNull(); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, FUZZY_TRANSPOSITIONS_FIELD)) { + fuzzyTranspositions = parser.booleanValue(); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, LENIENT_FIELD)) { + lenient = parser.booleanValue(); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, CUTOFF_FREQUENCY_FIELD)) { + cutOffFrequency = parser.floatValue(); + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, ZERO_TERMS_QUERY_FIELD)) { + String zeroTermsDocs = parser.text(); + if ("none".equalsIgnoreCase(zeroTermsDocs)) { + zeroTermsQuery = MatchQuery.ZeroTermsQuery.NONE; + } else if ("all".equalsIgnoreCase(zeroTermsDocs)) { + zeroTermsQuery = MatchQuery.ZeroTermsQuery.ALL; + } else { + throw new ParsingException(parser.getTokenLocation(), + "Unsupported zero_terms_docs value [" + zeroTermsDocs + "]"); + } + } else if (parseContext.getParseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.NAME_FIELD)) { + queryName = parser.text(); } else { throw new ParsingException(parser.getTokenLocation(), - "Unsupported zero_terms_docs value [" + zeroTermsDocs + "]"); + "[" + NAME + "] query does not support [" + currentFieldName + "]"); } - } else if (parseContext.getParseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.NAME_FIELD)) { - queryName = parser.text(); } else { throw new ParsingException(parser.getTokenLocation(), - "[" + NAME + "] query does not support [" + currentFieldName + "]"); + "[" + NAME + "] unknown token [" + token + "] after [" + currentFieldName + "]"); } - } else { - throw new ParsingException(parser.getTokenLocation(), - "[" + NAME + "] unknown token [" + token + "] after [" + currentFieldName + "]"); } - } - parser.nextToken(); - } else { - value = parser.objectText(); - // move to the next token - token = parser.nextToken(); - if (token != XContentParser.Token.END_OBJECT) { - throw new ParsingException(parser.getTokenLocation(), "[match] query parsed in simplified form, with direct field name, " - + "but included more options than just the field name, possibly use its 'options' form, with 'query' element?"); + } else { + fieldName = parser.currentName(); + value = parser.objectText(); } } diff --git a/core/src/test/java/org/elasticsearch/index/query/MatchQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/MatchQueryBuilderTests.java index 6a9a07c59dd..8772b360633 100644 --- a/core/src/test/java/org/elasticsearch/index/query/MatchQueryBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/MatchQueryBuilderTests.java @@ -29,6 +29,7 @@ import org.apache.lucene.search.PointRangeQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.elasticsearch.common.ParseFieldMatcher; +import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.lucene.search.MatchNoDocsQuery; import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery; import org.elasticsearch.common.lucene.search.Queries; @@ -40,7 +41,9 @@ import org.elasticsearch.test.AbstractQueryTestCase; import org.hamcrest.Matcher; import java.io.IOException; +import java.util.HashMap; import java.util.Locale; +import java.util.Map; import static org.hamcrest.CoreMatchers.either; import static org.hamcrest.CoreMatchers.instanceOf; @@ -118,6 +121,19 @@ public class MatchQueryBuilderTests extends AbstractQueryTestCase getAlternateVersions() { + Map alternateVersions = new HashMap<>(); + MatchQueryBuilder matchQuery = new MatchQueryBuilder(randomAsciiOfLengthBetween(1, 10), randomAsciiOfLengthBetween(1, 10)); + String contentString = "{\n" + + " \"match\" : {\n" + + " \"" + matchQuery.fieldName() + "\" : \"" + matchQuery.value() + "\"\n" + + " }\n" + + "}"; + alternateVersions.put(contentString, matchQuery); + return alternateVersions; + } + @Override protected void doAssertLuceneQuery(MatchQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException { assertThat(query, notNullValue()); @@ -406,4 +422,24 @@ public class MatchQueryBuilderTests extends AbstractQueryTestCase