Skip to content

Commit 42c5054

Browse files
committed
Fix alias field resolution in match query (#47369)
Synonym queries (when two tokens/paths start at the same position) use the alias field instead of the concrete field to build Lucene queries. This commit fixes this bug by resolving the alias field upfront in order to provide the concrete field to the actual query parser.
1 parent 033aa9c commit 42c5054

File tree

4 files changed

+32
-10
lines changed

4 files changed

+32
-10
lines changed

server/src/main/java/org/elasticsearch/index/search/MatchQuery.java

+17-8
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import java.util.ArrayList;
6363
import java.util.Iterator;
6464
import java.util.List;
65+
import java.util.Set;
6566
import java.util.function.Supplier;
6667

6768
import static org.elasticsearch.common.lucene.search.Queries.newLenientFieldQuery;
@@ -248,6 +249,14 @@ public Query parse(Type type, String fieldName, Object value) throws IOException
248249
if (fieldType == null) {
249250
return newUnmappedFieldQuery(fieldName);
250251
}
252+
Set<String> fields = context.simpleMatchToIndexNames(fieldName);
253+
if (fields.contains(fieldName)) {
254+
assert fields.size() == 1;
255+
// this field is a concrete field or an alias so we use the
256+
// field type name directly
257+
fieldName = fieldType.name();
258+
}
259+
251260
Analyzer analyzer = getAnalyzer(fieldType, type == Type.PHRASE || type == Type.PHRASE_PREFIX);
252261
assert analyzer != null;
253262

@@ -261,9 +270,9 @@ public Query parse(Type type, String fieldName, Object value) throws IOException
261270
*/
262271
if (analyzer == Lucene.KEYWORD_ANALYZER && type != Type.PHRASE_PREFIX) {
263272
final Term term = new Term(fieldName, value.toString());
264-
if ((fieldType instanceof TextFieldMapper.TextFieldType || fieldType instanceof KeywordFieldMapper.KeywordFieldType)
265-
&& type == Type.BOOLEAN_PREFIX) {
266-
return builder.newPrefixQuery(fieldName, term);
273+
if (type == Type.BOOLEAN_PREFIX
274+
&& (fieldType instanceof TextFieldMapper.TextFieldType || fieldType instanceof KeywordFieldMapper.KeywordFieldType)) {
275+
return builder.newPrefixQuery(term);
267276
} else {
268277
return builder.newTermQuery(term);
269278
}
@@ -581,12 +590,12 @@ protected Query newTermQuery(Term term) {
581590
/**
582591
* Builds a new prefix query instance.
583592
*/
584-
protected Query newPrefixQuery(String field, Term term) {
593+
protected Query newPrefixQuery(Term term) {
585594
try {
586595
return fieldType.prefixQuery(term.text(), null, context);
587596
} catch (RuntimeException e) {
588597
if (lenient) {
589-
return newLenientFieldQuery(field, e);
598+
return newLenientFieldQuery(term.field(), e);
590599
}
591600
throw e;
592601
}
@@ -603,7 +612,7 @@ private Query analyzeTerm(String field, TokenStream stream, boolean isPrefix) th
603612
final Term term = new Term(field, termAtt.getBytesRef());
604613
int lastOffset = offsetAtt.endOffset();
605614
stream.end();
606-
return isPrefix && lastOffset == offsetAtt.endOffset() ? newPrefixQuery(field, term) : newTermQuery(term);
615+
return isPrefix && lastOffset == offsetAtt.endOffset() ? newPrefixQuery(term) : newTermQuery(term);
607616
}
608617

609618
private void add(BooleanQuery.Builder q, String field, List<Term> current, BooleanClause.Occur operator, boolean isPrefix) {
@@ -612,7 +621,7 @@ private void add(BooleanQuery.Builder q, String field, List<Term> current, Boole
612621
}
613622
if (current.size() == 1) {
614623
if (isPrefix) {
615-
q.add(newPrefixQuery(field, current.get(0)), operator);
624+
q.add(newPrefixQuery(current.get(0)), operator);
616625
} else {
617626
q.add(newTermQuery(current.get(0)), operator);
618627
}
@@ -729,7 +738,7 @@ public Query next() {
729738
Term[] terms = graph.getTerms(field, start);
730739
assert terms.length > 0;
731740
if (terms.length == 1) {
732-
queryPos = usePrefix ? newPrefixQuery(field, terms[0]) : newTermQuery(terms[0]);
741+
queryPos = usePrefix ? newPrefixQuery(terms[0]) : newTermQuery(terms[0]);
733742
} else {
734743
// We don't apply prefix on synonyms
735744
queryPos = newSynonymQuery(terms);

server/src/main/java/org/elasticsearch/index/search/MultiMatchQuery.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ protected Query newTermQuery(Term term) {
194194
}
195195

196196
@Override
197-
protected Query newPrefixQuery(String field, Term term) {
197+
protected Query newPrefixQuery(Term term) {
198198
List<Query> disjunctions = new ArrayList<>();
199199
for (FieldAndBoost fieldType : blendedFields) {
200200
Query query = fieldType.fieldType.prefixQuery(term.text(), null, context);

server/src/main/java/org/elasticsearch/index/search/QueryParserHelper.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public static Map<String, Float> parseFieldsAndWeights(List<String> fields) {
5252
float boost = 1.0f;
5353
if (boostIndex != -1) {
5454
fieldName = field.substring(0, boostIndex);
55-
boost = Float.parseFloat(field.substring(boostIndex+1, field.length()));
55+
boost = Float.parseFloat(field.substring(boostIndex+1));
5656
} else {
5757
fieldName = field;
5858
}

server/src/test/java/org/elasticsearch/index/query/MatchQueryBuilderTests.java

+13
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.apache.lucene.search.PhraseQuery;
3333
import org.apache.lucene.search.PointRangeQuery;
3434
import org.apache.lucene.search.Query;
35+
import org.apache.lucene.search.SynonymQuery;
3536
import org.apache.lucene.search.TermQuery;
3637
import org.apache.lucene.search.spans.SpanNearQuery;
3738
import org.apache.lucene.search.spans.SpanOrQuery;
@@ -488,6 +489,18 @@ public void testMultiWordSynonymsPhrase() throws Exception {
488489
assertEquals(expected, actual);
489490
}
490491

492+
493+
public void testAliasWithSynonyms() throws Exception {
494+
final MatchQuery matchQuery = new MatchQuery(createShardContext());
495+
matchQuery.setAnalyzer(new MockSynonymAnalyzer());
496+
final Query actual = matchQuery.parse(Type.PHRASE, STRING_ALIAS_FIELD_NAME, "dogs");
497+
Query expected = new SynonymQuery.Builder(STRING_FIELD_NAME)
498+
.addTerm(new Term(STRING_FIELD_NAME, "dogs"))
499+
.addTerm(new Term(STRING_FIELD_NAME, "dog"))
500+
.build();
501+
assertEquals(expected, actual);
502+
}
503+
491504
public void testMaxBooleanClause() {
492505
MatchQuery query = new MatchQuery(createShardContext());
493506
query.setAnalyzer(new MockGraphAnalyzer(createGiantGraph(40)));

0 commit comments

Comments
 (0)