Fix problem with MatchNoDocsQuery in disjunction queries (#35726)

Queries across multiple fields generate MatchNoDocsQuerys for fields that are
unmapped. In certain situation this can lead to erroneous behaviour,
for example when an umapped field is used in a query_string query across
several fields. If some of the tokens in the query string get eliminated by an
analyzer on the mapped fields, the same token will currently generate
MatchNoDocsQuerys combined into a disjunction, which in turn
leads to no matches in the overall query. Instead we should simply not add
MatchNoDocsQuerys to those disjunctions.

Closes #34708
This commit is contained in:
Christoph Büscher 2018-11-21 03:49:49 +01:00 committed by GitHub
parent fa6d8a5004
commit ff03443ab9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 1 deletions

View File

@ -391,6 +391,7 @@ public class MatchQuery {
* Checks if graph analysis should be enabled for the field depending
* on the provided {@link Analyzer}
*/
@Override
protected Query createFieldQuery(Analyzer analyzer, BooleanClause.Occur operator, String field,
String queryText, boolean quoted, int phraseSlop) {
assert operator == BooleanClause.Occur.SHOULD || operator == BooleanClause.Occur.MUST;

View File

@ -120,7 +120,10 @@ public class MultiMatchQuery extends MatchQuery {
return queries;
}
public Query parseGroup(Type type, String field, Float boostValue, Object value, String minimumShouldMatch) throws IOException {
Query parseGroup(Type type, String field, Float boostValue, Object value, String minimumShouldMatch) throws IOException {
if (context.fieldMapper(field) == null) {
return null; // indicates to the caller that this field is unmapped and should be disregarded
}
return parseAndApply(type, field, value, minimumShouldMatch, boostValue);
}

View File

@ -687,6 +687,26 @@ public class SimpleQueryStringBuilderTests extends AbstractQueryTestCase<SimpleQ
assertEquals(expected, query);
}
/**
* Test for behavior reported in https://github.com/elastic/elasticsearch/issues/34708
* Unmapped field can lead to MatchNoDocsQuerys in disjunction queries. If tokens are eliminated (e.g. because
* the tokenizer removed them as punctuation) on regular fields, this can leave only MatchNoDocsQuerys in the
* disjunction clause. Instead those disjunctions should be eliminated completely.
*/
public void testUnmappedFieldNoTokenWithAndOperator() throws IOException {
Query query = new SimpleQueryStringBuilder("first & second")
.field(STRING_FIELD_NAME)
.field("unmapped")
.field("another_unmapped")
.defaultOperator(Operator.AND)
.toQuery(createShardContext());
BooleanQuery expected = new BooleanQuery.Builder()
.add(new TermQuery(new Term(STRING_FIELD_NAME, "first")), BooleanClause.Occur.MUST)
.add(new TermQuery(new Term(STRING_FIELD_NAME, "second")), BooleanClause.Occur.MUST)
.build();
assertEquals(expected, query);
}
private static IndexMetaData newIndexMeta(String name, Settings oldIndexSettings, Settings indexSettings) {
Settings build = Settings.builder().put(oldIndexSettings)
.put(indexSettings)