Fix wrong logic in `match_phrase` query with multi-word synonyms (#43941)

Disjunction over two individual terms in a phrase query with multi-word synonyms
wrongly applies a prefix query to each of these terms. This change fixes this bug
by inversing the logic to use prefixes on `phrase_prefix` queries only.

Closes #43308
This commit is contained in:
Jim Ferenczi 2019-07-04 09:38:56 +02:00 committed by jimczi
parent cacc3f7ff8
commit 2cc0a56fe6
2 changed files with 29 additions and 2 deletions

View File

@ -509,8 +509,8 @@ public class MatchQuery {
} }
SpanQuery[] spanQueries = new SpanQuery[terms.length]; SpanQuery[] spanQueries = new SpanQuery[terms.length];
for (int i = 0; i < terms.length; i++) { for (int i = 0; i < terms.length; i++) {
spanQueries[i] = isPrefix ? new SpanTermQuery(terms[i]) : spanQueries[i] = isPrefix ? fieldType.spanPrefixQuery(terms[i].text(), spanRewriteMethod, context) :
fieldType.spanPrefixQuery(terms[i].text(), spanRewriteMethod, context); new SpanTermQuery(terms[i]);
} }
return new SpanOrQuery(spanQueries); return new SpanOrQuery(spanQueries);
} }

View File

@ -33,6 +33,10 @@ import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.PointRangeQuery; import org.apache.lucene.search.PointRangeQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.spans.SpanNearQuery;
import org.apache.lucene.search.spans.SpanOrQuery;
import org.apache.lucene.search.spans.SpanQuery;
import org.apache.lucene.search.spans.SpanTermQuery;
import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRef;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.ParsingException;
@ -463,6 +467,29 @@ public class MatchQueryBuilderTests extends AbstractQueryTestCase<MatchQueryBuil
} }
} }
public void testMultiWordSynonymsPhrase() throws Exception {
final MatchQuery matchQuery = new MatchQuery(createShardContext());
matchQuery.setAnalyzer(new MockSynonymAnalyzer());
final Query actual = matchQuery.parse(Type.PHRASE, STRING_FIELD_NAME, "guinea pig dogs");
Query expected = SpanNearQuery.newOrderedNearQuery(STRING_FIELD_NAME)
.addClause(
new SpanOrQuery(new SpanQuery[]{
SpanNearQuery.newOrderedNearQuery(STRING_FIELD_NAME)
.addClause(new SpanTermQuery(new Term(STRING_FIELD_NAME, "guinea")))
.addClause(new SpanTermQuery(new Term(STRING_FIELD_NAME, "pig")))
.setSlop(0)
.build(),
new SpanTermQuery(new Term(STRING_FIELD_NAME, "cavy"))
})
)
.addClause(new SpanOrQuery(new SpanQuery[]{
new SpanTermQuery(new Term(STRING_FIELD_NAME, "dogs")),
new SpanTermQuery(new Term(STRING_FIELD_NAME, "dog"))
}))
.build();
assertEquals(expected, actual);
}
public void testMaxBooleanClause() { public void testMaxBooleanClause() {
MatchQuery query = new MatchQuery(createShardContext()); MatchQuery query = new MatchQuery(createShardContext());
query.setAnalyzer(new MockGraphAnalyzer(createGiantGraph(40))); query.setAnalyzer(new MockGraphAnalyzer(createGiantGraph(40)));