diff --git a/server/src/main/java/org/elasticsearch/index/search/MatchQuery.java b/server/src/main/java/org/elasticsearch/index/search/MatchQuery.java index d6a0bf5f738..03b4715c4b1 100644 --- a/server/src/main/java/org/elasticsearch/index/search/MatchQuery.java +++ b/server/src/main/java/org/elasticsearch/index/search/MatchQuery.java @@ -102,7 +102,10 @@ public class MatchQuery { public enum ZeroTermsQuery implements Writeable { NONE(0), - ALL(1); + ALL(1), + // this is used internally to make sure that query_string and simple_query_string + // ignores query part that removes all tokens. + NULL(2); private final int ordinal; @@ -312,10 +315,16 @@ public class MatchQuery { } protected Query zeroTermsQuery() { - if (zeroTermsQuery == DEFAULT_ZERO_TERMS_QUERY) { - return Queries.newMatchNoDocsQuery("Matching no documents because no terms present."); + switch (zeroTermsQuery) { + case NULL: + return null; + case NONE: + return Queries.newMatchNoDocsQuery("Matching no documents because no terms present"); + case ALL: + return Queries.newMatchAllQuery(); + default: + throw new IllegalStateException("unknown zeroTermsQuery " + zeroTermsQuery); } - return Queries.newMatchAllQuery(); } private class MatchQueryBuilder extends QueryBuilder { diff --git a/server/src/main/java/org/elasticsearch/index/search/QueryStringQueryParser.java b/server/src/main/java/org/elasticsearch/index/search/QueryStringQueryParser.java index 5f453d49ab5..9341a872543 100644 --- a/server/src/main/java/org/elasticsearch/index/search/QueryStringQueryParser.java +++ b/server/src/main/java/org/elasticsearch/index/search/QueryStringQueryParser.java @@ -147,6 +147,7 @@ public class QueryStringQueryParser extends XQueryParser { this.context = context; this.fieldsAndWeights = Collections.unmodifiableMap(fieldsAndWeights); this.queryBuilder = new MultiMatchQuery(context); + queryBuilder.setZeroTermsQuery(MatchQuery.ZeroTermsQuery.NULL); queryBuilder.setLenient(lenient); this.lenient = lenient; } @@ -343,7 +344,6 @@ public class QueryStringQueryParser extends XQueryParser { if (fields.isEmpty()) { return newUnmappedFieldQuery(field); } - final Query query; Analyzer oldAnalyzer = queryBuilder.analyzer; int oldSlop = queryBuilder.phraseSlop; try { @@ -353,7 +353,7 @@ public class QueryStringQueryParser extends XQueryParser { queryBuilder.setAnalyzer(forceAnalyzer); } queryBuilder.setPhraseSlop(slop); - query = queryBuilder.parse(MultiMatchQueryBuilder.Type.PHRASE, fields, queryText, null); + Query query = queryBuilder.parse(MultiMatchQueryBuilder.Type.PHRASE, fields, queryText, null); return applySlop(query, slop); } catch (IOException e) { throw new ParseException(e.getMessage()); @@ -555,7 +555,7 @@ public class QueryStringQueryParser extends XQueryParser { } if (tlist.size() == 0) { - return new MatchNoDocsQuery("analysis was empty for " + field + ":" + termStr); + return super.getPrefixQuery(field, termStr); } if (tlist.size() == 1 && tlist.get(0).size() == 1) { @@ -763,7 +763,7 @@ public class QueryStringQueryParser extends XQueryParser { @Override public Query parse(String query) throws ParseException { if (query.trim().isEmpty()) { - return queryBuilder.zeroTermsQuery(); + return Queries.newMatchNoDocsQuery("Matching no documents because no terms present"); } return super.parse(query); } diff --git a/server/src/main/java/org/elasticsearch/index/search/SimpleQueryStringQueryParser.java b/server/src/main/java/org/elasticsearch/index/search/SimpleQueryStringQueryParser.java index aea3677e33e..c4048887cf9 100644 --- a/server/src/main/java/org/elasticsearch/index/search/SimpleQueryStringQueryParser.java +++ b/server/src/main/java/org/elasticsearch/index/search/SimpleQueryStringQueryParser.java @@ -74,6 +74,7 @@ public class SimpleQueryStringQueryParser extends SimpleQueryParser { this.queryBuilder = new MultiMatchQuery(context); this.queryBuilder.setAutoGenerateSynonymsPhraseQuery(settings.autoGenerateSynonymsPhraseQuery()); this.queryBuilder.setLenient(settings.lenient()); + this.queryBuilder.setZeroTermsQuery(MatchQuery.ZeroTermsQuery.NULL); if (analyzer != null) { this.queryBuilder.setAnalyzer(analyzer); } diff --git a/server/src/test/java/org/elasticsearch/index/query/MatchQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/MatchQueryBuilderTests.java index 00a9753b6f8..e8699897d66 100644 --- a/server/src/test/java/org/elasticsearch/index/query/MatchQueryBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/MatchQueryBuilderTests.java @@ -111,7 +111,7 @@ public class MatchQueryBuilderTests extends AbstractQueryTestCase 0); + Query query = new QueryStringQueryBuilder("the quick fox") + .field(STRING_FIELD_NAME) + .analyzer("english") + .toQuery(createShardContext()); + BooleanQuery expected = new BooleanQuery.Builder() + .add(new TermQuery(new Term(STRING_FIELD_NAME, "quick")), Occur.SHOULD) + .add(new TermQuery(new Term(STRING_FIELD_NAME, "fox")), Occur.SHOULD) + .build(); + assertEquals(expected, query); + } + + public void testWithPrefixStopWords() throws Exception { + assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); + Query query = new QueryStringQueryBuilder("the* quick fox") + .field(STRING_FIELD_NAME) + .analyzer("english") + .toQuery(createShardContext()); + BooleanQuery expected = new BooleanQuery.Builder() + .add(new PrefixQuery(new Term(STRING_FIELD_NAME, "the")), Occur.SHOULD) + .add(new TermQuery(new Term(STRING_FIELD_NAME, "quick")), Occur.SHOULD) + .add(new TermQuery(new Term(STRING_FIELD_NAME, "fox")), Occur.SHOULD) + .build(); + assertEquals(expected, query); + } + private static IndexMetaData newIndexMeta(String name, Settings oldIndexSettings, Settings indexSettings) { Settings build = Settings.builder().put(oldIndexSettings) .put(indexSettings) diff --git a/server/src/test/java/org/elasticsearch/index/query/SimpleQueryStringBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/SimpleQueryStringBuilderTests.java index dc7c56ce04e..7ff2b7ec122 100644 --- a/server/src/test/java/org/elasticsearch/index/query/SimpleQueryStringBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/SimpleQueryStringBuilderTests.java @@ -625,6 +625,33 @@ public class SimpleQueryStringBuilderTests extends AbstractQueryTestCase 0); + Query query = new SimpleQueryStringBuilder("the quick fox") + .field(STRING_FIELD_NAME) + .analyzer("english") + .toQuery(createShardContext()); + BooleanQuery expected = new BooleanQuery.Builder() + .add(new TermQuery(new Term(STRING_FIELD_NAME, "quick")), BooleanClause.Occur.SHOULD) + .add(new TermQuery(new Term(STRING_FIELD_NAME, "fox")), BooleanClause.Occur.SHOULD) + .build(); + assertEquals(expected, query); + } + + public void testWithPrefixStopWords() throws Exception { + assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); + Query query = new SimpleQueryStringBuilder("the* quick fox") + .field(STRING_FIELD_NAME) + .analyzer("english") + .toQuery(createShardContext()); + BooleanQuery expected = new BooleanQuery.Builder() + .add(new PrefixQuery(new Term(STRING_FIELD_NAME, "the")), BooleanClause.Occur.SHOULD) + .add(new TermQuery(new Term(STRING_FIELD_NAME, "quick")), BooleanClause.Occur.SHOULD) + .add(new TermQuery(new Term(STRING_FIELD_NAME, "fox")), BooleanClause.Occur.SHOULD) + .build(); + assertEquals(expected, query); + } + private static IndexMetaData newIndexMeta(String name, Settings oldIndexSettings, Settings indexSettings) { Settings build = Settings.builder().put(oldIndexSettings) .put(indexSettings)