diff --git a/core/src/main/java/org/apache/lucene/queryparser/classic/MapperQueryParser.java b/core/src/main/java/org/apache/lucene/queryparser/classic/MapperQueryParser.java index 79f522e8c1fe5..015972c568417 100644 --- a/core/src/main/java/org/apache/lucene/queryparser/classic/MapperQueryParser.java +++ b/core/src/main/java/org/apache/lucene/queryparser/classic/MapperQueryParser.java @@ -57,7 +57,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - +import java.util.Collections; import static java.util.Collections.unmodifiableMap; import static org.elasticsearch.common.lucene.search.Queries.fixNegativeQueryIfNeeded; @@ -91,7 +91,8 @@ public MapperQueryParser(QueryShardContext context) { public void reset(QueryParserSettings settings) { this.settings = settings; - if (settings.fieldsAndWeights().isEmpty()) { + if (settings.fieldsAndWeights() == null) { + // this query has no explicit fields to query so we fallback to the default field this.field = settings.defaultField(); } else if (settings.fieldsAndWeights().size() == 1) { this.field = settings.fieldsAndWeights().keySet().iterator().next(); @@ -148,6 +149,11 @@ public Query getFieldQuery(String field, String queryText, boolean quoted) throw if (fields != null) { if (fields.size() == 1) { return getFieldQuerySingle(fields.iterator().next(), queryText, quoted); + } else if (fields.isEmpty()) { + // the requested fields do not match any field in the mapping + // happens for wildcard fields only since we cannot expand to a valid field name + // if there is no match in the mappings. + return new MatchNoDocsQuery("empty fields"); } if (settings.useDisMax()) { List queries = new ArrayList<>(); @@ -721,7 +727,7 @@ protected Query getBooleanQuery(List clauses) throws ParseExcepti } private Query applyBoost(String field, Query q) { - Float fieldBoost = settings.fieldsAndWeights().get(field); + Float fieldBoost = settings.fieldsAndWeights() == null ? null : settings.fieldsAndWeights().get(field); if (fieldBoost != null && fieldBoost != 1f) { return new BoostQuery(q, fieldBoost); } @@ -780,7 +786,8 @@ private Collection extractMultiFields(String field) { if (field != null) { fields = context.simpleMatchToIndexNames(field); } else { - fields = settings.fieldsAndWeights().keySet(); + Map fieldsAndWeights = settings.fieldsAndWeights(); + fields = fieldsAndWeights == null ? Collections.emptyList() : settings.fieldsAndWeights().keySet(); } return fields; } 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 ca716372571cc..fd6f33e27ba87 100644 --- a/core/src/main/java/org/elasticsearch/index/query/QueryStringQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/QueryStringQueryBuilder.java @@ -981,7 +981,11 @@ protected Query doToQuery(QueryShardContext context) throws IOException { } qpSettings.lenient(lenient == null ? context.queryStringLenient() : lenient); } - qpSettings.fieldsAndWeights(resolvedFields); + if (fieldsAndWeights.isEmpty() == false || resolvedFields.isEmpty() == false) { + // We set the fields and weight only if we have explicit fields to query + // Otherwise we set it to null and fallback to the default field. + qpSettings.fieldsAndWeights(resolvedFields); + } qpSettings.defaultOperator(defaultOperator.toQueryParserOperator()); if (analyzer == null) { diff --git a/core/src/test/java/org/elasticsearch/index/query/QueryStringQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/QueryStringQueryBuilderTests.java index 86647233aa3fc..5b9990c81cd9e 100644 --- a/core/src/test/java/org/elasticsearch/index/query/QueryStringQueryBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/QueryStringQueryBuilderTests.java @@ -324,7 +324,6 @@ public void testToQueryWildcarQuery() throws Exception { MapperQueryParser queryParser = new MapperQueryParser(createShardContext()); QueryParserSettings settings = new QueryParserSettings("first foo-bar-foobar* last"); settings.defaultField(STRING_FIELD_NAME); - settings.fieldsAndWeights(Collections.emptyMap()); settings.analyzeWildcard(true); settings.fuzziness(Fuzziness.AUTO); settings.rewriteMethod(MultiTermQuery.CONSTANT_SCORE_REWRITE); @@ -352,7 +351,6 @@ public void testToQueryWilcardQueryWithSynonyms() throws Exception { MapperQueryParser queryParser = new MapperQueryParser(createShardContext()); QueryParserSettings settings = new QueryParserSettings("first foo-bar-foobar* last"); settings.defaultField(STRING_FIELD_NAME); - settings.fieldsAndWeights(Collections.emptyMap()); settings.analyzeWildcard(true); settings.fuzziness(Fuzziness.AUTO); settings.rewriteMethod(MultiTermQuery.CONSTANT_SCORE_REWRITE); @@ -390,7 +388,6 @@ public void testToQueryWithGraph() throws Exception { MapperQueryParser queryParser = new MapperQueryParser(createShardContext()); QueryParserSettings settings = new QueryParserSettings(""); settings.defaultField(STRING_FIELD_NAME); - settings.fieldsAndWeights(Collections.emptyMap()); settings.fuzziness(Fuzziness.AUTO); settings.analyzeWildcard(true); settings.rewriteMethod(MultiTermQuery.CONSTANT_SCORE_REWRITE); @@ -689,6 +686,29 @@ public void testToQueryPhraseQueryBoostAndSlop() throws IOException { assertThat(phraseQuery.getTerms().length, equalTo(2)); } + public void testToQueryWildcardNonExistingFields() throws IOException { + assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); + QueryStringQueryBuilder queryStringQueryBuilder = + new QueryStringQueryBuilder("foo bar").field("invalid*"); + Query query = queryStringQueryBuilder.toQuery(createShardContext()); + Query expectedQuery = new BooleanQuery.Builder() + .add(new MatchNoDocsQuery("empty fields"), Occur.SHOULD) + .add(new MatchNoDocsQuery("empty fields"), Occur.SHOULD) + .build(); + assertThat(expectedQuery, equalTo(query)); + + queryStringQueryBuilder = + new QueryStringQueryBuilder("field:foo bar").field("invalid*"); + query = queryStringQueryBuilder.toQuery(createShardContext()); + expectedQuery = new BooleanQuery.Builder() + .add(new TermQuery(new Term("field", "foo")), Occur.SHOULD) + .add(new MatchNoDocsQuery("empty fields"), Occur.SHOULD) + .build(); + assertThat(expectedQuery, equalTo(query)); + + + } + public void testToQuerySplitOnWhitespace() throws IOException { assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); // splitOnWhitespace=false