Fix multi fields empty query (#33017)

This change fixes empty query removal when all fields remove the search term in
`simple_query_string`, `multi_match` and `query_string`.

Closes #33009
This commit is contained in:
Jim Ferenczi 2018-08-21 22:12:53 +02:00 committed by GitHub
parent f311680176
commit 8b43e21521
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 172 additions and 9 deletions

View File

@ -328,8 +328,9 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
/** /**
* @param type Sets how multiple fields should be combined to build textual part queries. * @param type Sets how multiple fields should be combined to build textual part queries.
*/ */
public void type(MultiMatchQueryBuilder.Type type) { public QueryStringQueryBuilder type(MultiMatchQueryBuilder.Type type) {
this.type = type; this.type = type;
return this;
} }
/** /**

View File

@ -120,7 +120,7 @@ public class MultiMatchQuery extends MatchQuery {
private Query combineGrouped(List<? extends Query> groupQuery) { private Query combineGrouped(List<? extends Query> groupQuery) {
if (groupQuery == null || groupQuery.isEmpty()) { if (groupQuery == null || groupQuery.isEmpty()) {
return new MatchNoDocsQuery("[multi_match] list of group queries was empty"); return zeroTermsQuery();
} }
if (groupQuery.size() == 1) { if (groupQuery.size() == 1) {
return groupQuery.get(0); return groupQuery.get(0);

View File

@ -347,6 +347,9 @@ public class QueryStringQueryParser extends XQueryParser {
} }
queryBuilder.setPhraseSlop(slop); queryBuilder.setPhraseSlop(slop);
Query query = queryBuilder.parse(MultiMatchQueryBuilder.Type.PHRASE, fields, queryText, null); Query query = queryBuilder.parse(MultiMatchQueryBuilder.Type.PHRASE, fields, queryText, null);
if (query == null) {
return null;
}
return applySlop(query, slop); return applySlop(query, slop);
} catch (IOException e) { } catch (IOException e) {
throw new ParseException(e.getMessage()); throw new ParseException(e.getMessage());

View File

@ -21,6 +21,7 @@ package org.elasticsearch.index.query;
import org.apache.lucene.index.Term; import org.apache.lucene.index.Term;
import org.apache.lucene.queries.ExtendedCommonTermsQuery; import org.apache.lucene.queries.ExtendedCommonTermsQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery; import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.DisjunctionMaxQuery; import org.apache.lucene.search.DisjunctionMaxQuery;
@ -381,6 +382,69 @@ public class MultiMatchQueryBuilderTests extends AbstractQueryTestCase<MultiMatc
assertEquals(expected, query); assertEquals(expected, query);
} }
public void testWithStopWords() throws Exception {
Query query = new MultiMatchQueryBuilder("the quick fox")
.field(STRING_FIELD_NAME)
.analyzer("stop")
.toQuery(createShardContext());
Query 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);
query = new MultiMatchQueryBuilder("the quick fox")
.field(STRING_FIELD_NAME)
.field(STRING_FIELD_NAME_2)
.analyzer("stop")
.toQuery(createShardContext());
expected = new DisjunctionMaxQuery(
Arrays.asList(
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(),
new BooleanQuery.Builder()
.add(new TermQuery(new Term(STRING_FIELD_NAME_2, "quick")), BooleanClause.Occur.SHOULD)
.add(new TermQuery(new Term(STRING_FIELD_NAME_2, "fox")), BooleanClause.Occur.SHOULD)
.build()
), 0f);
assertEquals(expected, query);
query = new MultiMatchQueryBuilder("the")
.field(STRING_FIELD_NAME)
.field(STRING_FIELD_NAME_2)
.analyzer("stop")
.toQuery(createShardContext());
expected = new DisjunctionMaxQuery(Arrays.asList(new MatchNoDocsQuery(), new MatchNoDocsQuery()), 0f);
assertEquals(expected, query);
query = new BoolQueryBuilder()
.should(
new MultiMatchQueryBuilder("the")
.field(STRING_FIELD_NAME)
.analyzer("stop")
)
.toQuery(createShardContext());
expected = new BooleanQuery.Builder()
.add(new MatchNoDocsQuery(), BooleanClause.Occur.SHOULD)
.build();
assertEquals(expected, query);
query = new BoolQueryBuilder()
.should(
new MultiMatchQueryBuilder("the")
.field(STRING_FIELD_NAME)
.field(STRING_FIELD_NAME_2)
.analyzer("stop")
)
.toQuery(createShardContext());
expected = new BooleanQuery.Builder()
.add(new DisjunctionMaxQuery(Arrays.asList(new MatchNoDocsQuery(), new MatchNoDocsQuery()), 0f), BooleanClause.Occur.SHOULD)
.build();
assertEquals(expected, query);
}
private static IndexMetaData newIndexMeta(String name, Settings oldIndexSettings, Settings indexSettings) { private static IndexMetaData newIndexMeta(String name, Settings oldIndexSettings, Settings indexSettings) {
Settings build = Settings.builder().put(oldIndexSettings) Settings build = Settings.builder().put(oldIndexSettings)
.put(indexSettings) .put(indexSettings)

View File

@ -1266,11 +1266,58 @@ public class QueryStringQueryBuilderTests extends AbstractQueryTestCase<QueryStr
.field(STRING_FIELD_NAME) .field(STRING_FIELD_NAME)
.analyzer("stop") .analyzer("stop")
.toQuery(createShardContext()); .toQuery(createShardContext());
BooleanQuery expected = new BooleanQuery.Builder() Query 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);
query = new QueryStringQueryBuilder("the quick fox")
.field(STRING_FIELD_NAME)
.field(STRING_FIELD_NAME_2)
.analyzer("stop")
.toQuery(createShardContext());
expected = new DisjunctionMaxQuery(
Arrays.asList(
new BooleanQuery.Builder()
.add(new TermQuery(new Term(STRING_FIELD_NAME, "quick")), Occur.SHOULD) .add(new TermQuery(new Term(STRING_FIELD_NAME, "quick")), Occur.SHOULD)
.add(new TermQuery(new Term(STRING_FIELD_NAME, "fox")), Occur.SHOULD) .add(new TermQuery(new Term(STRING_FIELD_NAME, "fox")), Occur.SHOULD)
.build(),
new BooleanQuery.Builder()
.add(new TermQuery(new Term(STRING_FIELD_NAME_2, "quick")), Occur.SHOULD)
.add(new TermQuery(new Term(STRING_FIELD_NAME_2, "fox")), Occur.SHOULD)
.build()
), 0f);
assertEquals(expected, query);
query = new QueryStringQueryBuilder("the")
.field(STRING_FIELD_NAME)
.field(STRING_FIELD_NAME_2)
.analyzer("stop")
.toQuery(createShardContext());
assertEquals(new BooleanQuery.Builder().build(), query);
query = new BoolQueryBuilder()
.should(
new QueryStringQueryBuilder("the")
.field(STRING_FIELD_NAME)
.analyzer("stop")
)
.toQuery(createShardContext());
expected = new BooleanQuery.Builder()
.add(new BooleanQuery.Builder().build(), BooleanClause.Occur.SHOULD)
.build(); .build();
assertEquals(expected, query); assertEquals(expected, query);
query = new BoolQueryBuilder()
.should(
new QueryStringQueryBuilder("the")
.field(STRING_FIELD_NAME)
.field(STRING_FIELD_NAME_2)
.analyzer("stop")
)
.toQuery(createShardContext());
assertEquals(expected, query);
} }
public void testWithPrefixStopWords() throws Exception { public void testWithPrefixStopWords() throws Exception {

View File

@ -613,11 +613,59 @@ public class SimpleQueryStringBuilderTests extends AbstractQueryTestCase<SimpleQ
.field(STRING_FIELD_NAME) .field(STRING_FIELD_NAME)
.analyzer("stop") .analyzer("stop")
.toQuery(createShardContext()); .toQuery(createShardContext());
BooleanQuery expected = new BooleanQuery.Builder() Query expected = new BooleanQuery.Builder()
.add(new TermQuery(new Term(STRING_FIELD_NAME, "quick")), 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) .add(new TermQuery(new Term(STRING_FIELD_NAME, "fox")), BooleanClause.Occur.SHOULD)
.build(); .build();
assertEquals(expected, query); assertEquals(expected, query);
query = new SimpleQueryStringBuilder("the quick fox")
.field(STRING_FIELD_NAME)
.field(STRING_FIELD_NAME_2)
.analyzer("stop")
.toQuery(createShardContext());
expected = new BooleanQuery.Builder()
.add(new DisjunctionMaxQuery(
Arrays.asList(
new TermQuery(new Term(STRING_FIELD_NAME, "quick")),
new TermQuery(new Term(STRING_FIELD_NAME_2, "quick"))
), 1.0f), BooleanClause.Occur.SHOULD)
.add(new DisjunctionMaxQuery(
Arrays.asList(
new TermQuery(new Term(STRING_FIELD_NAME, "fox")),
new TermQuery(new Term(STRING_FIELD_NAME_2, "fox"))
), 1.0f), BooleanClause.Occur.SHOULD)
.build();
assertEquals(expected, query);
query = new SimpleQueryStringBuilder("the")
.field(STRING_FIELD_NAME)
.field(STRING_FIELD_NAME_2)
.analyzer("stop")
.toQuery(createShardContext());
assertEquals(new MatchNoDocsQuery(), query);
query = new BoolQueryBuilder()
.should(
new SimpleQueryStringBuilder("the")
.field(STRING_FIELD_NAME)
.analyzer("stop")
)
.toQuery(createShardContext());
expected = new BooleanQuery.Builder()
.add(new MatchNoDocsQuery(), BooleanClause.Occur.SHOULD)
.build();
assertEquals(expected, query);
query = new BoolQueryBuilder()
.should(
new SimpleQueryStringBuilder("the")
.field(STRING_FIELD_NAME)
.field(STRING_FIELD_NAME_2)
.analyzer("stop")
)
.toQuery(createShardContext());
assertEquals(expected, query);
} }
public void testWithPrefixStopWords() throws Exception { public void testWithPrefixStopWords() throws Exception {