Fix match_phrase_prefix on boosted fields (#21623)

This change fixes the match_phrase_prefix on fields that define a boost in their mapping.

Fixes #21613
This commit is contained in:
Jim Ferenczi 2016-11-17 18:45:34 +01:00 committed by GitHub
parent 914664d89a
commit 09fbb4d06d
2 changed files with 56 additions and 12 deletions

View File

@ -25,6 +25,7 @@ import org.apache.lucene.queries.ExtendedCommonTermsQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.MultiPhraseQuery;
import org.apache.lucene.search.MultiTermQuery;
@ -303,31 +304,38 @@ public class MatchQuery {
public Query createPhrasePrefixQuery(String field, String queryText, int phraseSlop, int maxExpansions) {
final Query query = createFieldQuery(getAnalyzer(), Occur.MUST, field, queryText, true, phraseSlop);
float boost = 1;
Query innerQuery = query;
while (innerQuery instanceof BoostQuery) {
BoostQuery bq = (BoostQuery) innerQuery;
boost *= bq.getBoost();
innerQuery = bq.getQuery();
}
final MultiPhrasePrefixQuery prefixQuery = new MultiPhrasePrefixQuery();
prefixQuery.setMaxExpansions(maxExpansions);
prefixQuery.setSlop(phraseSlop);
if (query instanceof PhraseQuery) {
PhraseQuery pq = (PhraseQuery)query;
if (innerQuery instanceof PhraseQuery) {
PhraseQuery pq = (PhraseQuery) innerQuery;
Term[] terms = pq.getTerms();
int[] positions = pq.getPositions();
for (int i = 0; i < terms.length; i++) {
prefixQuery.add(new Term[] {terms[i]}, positions[i]);
}
return prefixQuery;
} else if (query instanceof MultiPhraseQuery) {
MultiPhraseQuery pq = (MultiPhraseQuery)query;
return boost == 1 ? prefixQuery : new BoostQuery(prefixQuery, boost);
} else if (innerQuery instanceof MultiPhraseQuery) {
MultiPhraseQuery pq = (MultiPhraseQuery) innerQuery;
Term[][] terms = pq.getTermArrays();
int[] positions = pq.getPositions();
for (int i = 0; i < terms.length; i++) {
prefixQuery.add(terms[i], positions[i]);
}
return prefixQuery;
} else if (query instanceof TermQuery) {
prefixQuery.add(((TermQuery) query).getTerm());
return prefixQuery;
} else if (query instanceof AllTermQuery) {
prefixQuery.add(((AllTermQuery) query).getTerm());
return prefixQuery;
return boost == 1 ? prefixQuery : new BoostQuery(prefixQuery, boost);
} else if (innerQuery instanceof TermQuery) {
prefixQuery.add(((TermQuery) innerQuery).getTerm());
return boost == 1 ? prefixQuery : new BoostQuery(prefixQuery, boost);
} else if (innerQuery instanceof AllTermQuery) {
prefixQuery.add(((AllTermQuery) innerQuery).getTerm());
return boost == 1 ? prefixQuery : new BoostQuery(prefixQuery, boost);
}
return query;
}

View File

@ -22,6 +22,7 @@ package org.elasticsearch.index.query;
import org.apache.lucene.queries.ExtendedCommonTermsQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
@ -29,11 +30,15 @@ import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.PointRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.elasticsearch.Version;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.search.MatchQuery;
import org.elasticsearch.index.search.MatchQuery.Type;
import org.elasticsearch.index.search.MatchQuery.ZeroTermsQuery;
@ -458,4 +463,35 @@ public class MatchQueryBuilderTests extends AbstractQueryTestCase<MatchQueryBuil
"}";
expectThrows(IllegalStateException.class, () -> parseQuery(json2));
}
@Override
protected void initializeAdditionalMappings(MapperService mapperService) throws IOException {
mapperService.merge("t_boost", new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef("t_boost",
"string_boost", "type=text,boost=4").string()), MapperService.MergeReason.MAPPING_UPDATE, false);
}
public void testMatchPhrasePrefixWithBoost() throws Exception {
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
QueryShardContext context = createShardContext();
assumeTrue("test runs only when the index version is on or after V_5_0_0_alpha1",
context.indexVersionCreated().onOrAfter(Version.V_5_0_0_alpha1));
{
// field boost is applied on a single term query
MatchPhrasePrefixQueryBuilder builder = new MatchPhrasePrefixQueryBuilder("string_boost", "foo");
Query query = builder.toQuery(context);
assertThat(query, instanceOf(BoostQuery.class));
assertThat(((BoostQuery) query).getBoost(), equalTo(4f));
Query innerQuery = ((BoostQuery) query).getQuery();
assertThat(innerQuery, instanceOf(MultiPhrasePrefixQuery.class));
}
{
// field boost is ignored on phrase query
MatchPhrasePrefixQueryBuilder builder = new MatchPhrasePrefixQueryBuilder("string_boost", "foo bar");
Query query = builder.toQuery(context);
assertThat(query, instanceOf(MultiPhrasePrefixQuery.class));
}
}
}