Currently `match_phrase_prefix` doesn't support `zero_terms_query` like the other match-type queries. This change adds this support. Closes #58468
This commit is contained in:
parent
6ccf3548e7
commit
f4ff5fe93b
|
@ -21,6 +21,7 @@ package org.elasticsearch.index.query;
|
|||
|
||||
import org.apache.lucene.search.FuzzyQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
|
@ -28,6 +29,7 @@ import org.elasticsearch.common.io.stream.StreamOutput;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.search.MatchQuery;
|
||||
import org.elasticsearch.index.search.MatchQuery.ZeroTermsQuery;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
@ -39,6 +41,7 @@ import java.util.Objects;
|
|||
public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhrasePrefixQueryBuilder> {
|
||||
public static final String NAME = "match_phrase_prefix";
|
||||
public static final ParseField MAX_EXPANSIONS_FIELD = new ParseField("max_expansions");
|
||||
public static final ParseField ZERO_TERMS_QUERY_FIELD = new ParseField("zero_terms_query");
|
||||
|
||||
private final String fieldName;
|
||||
|
||||
|
@ -50,6 +53,8 @@ public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhr
|
|||
|
||||
private int maxExpansions = FuzzyQuery.defaultMaxExpansions;
|
||||
|
||||
private ZeroTermsQuery zeroTermsQuery = MatchQuery.DEFAULT_ZERO_TERMS_QUERY;
|
||||
|
||||
public MatchPhrasePrefixQueryBuilder(String fieldName, Object value) {
|
||||
if (fieldName == null) {
|
||||
throw new IllegalArgumentException("[" + NAME + "] requires fieldName");
|
||||
|
@ -71,6 +76,9 @@ public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhr
|
|||
slop = in.readVInt();
|
||||
maxExpansions = in.readVInt();
|
||||
analyzer = in.readOptionalString();
|
||||
if (in.getVersion().onOrAfter(Version.V_7_10_0)) {
|
||||
this.zeroTermsQuery = ZeroTermsQuery.readFromStream(in);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -80,6 +88,9 @@ public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhr
|
|||
out.writeVInt(slop);
|
||||
out.writeVInt(maxExpansions);
|
||||
out.writeOptionalString(analyzer);
|
||||
if (out.getVersion().onOrAfter(Version.V_7_10_0)) {
|
||||
zeroTermsQuery.writeTo(out);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the field name used in this query. */
|
||||
|
@ -139,6 +150,23 @@ public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhr
|
|||
return this.maxExpansions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets query to use in case no query terms are available, e.g. after analysis removed them.
|
||||
* Defaults to {@link ZeroTermsQuery#NONE}, but can be set to
|
||||
* {@link ZeroTermsQuery#ALL} instead.
|
||||
*/
|
||||
public MatchPhrasePrefixQueryBuilder zeroTermsQuery(ZeroTermsQuery zeroTermsQuery) {
|
||||
if (zeroTermsQuery == null) {
|
||||
throw new IllegalArgumentException("[" + NAME + "] requires zeroTermsQuery to be non-null");
|
||||
}
|
||||
this.zeroTermsQuery = zeroTermsQuery;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ZeroTermsQuery zeroTermsQuery() {
|
||||
return this.zeroTermsQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWriteableName() {
|
||||
return NAME;
|
||||
|
@ -155,6 +183,7 @@ public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhr
|
|||
}
|
||||
builder.field(MatchPhraseQueryBuilder.SLOP_FIELD.getPreferredName(), slop);
|
||||
builder.field(MAX_EXPANSIONS_FIELD.getPreferredName(), maxExpansions);
|
||||
builder.field(ZERO_TERMS_QUERY_FIELD.getPreferredName(), zeroTermsQuery.toString());
|
||||
printBoostAndQueryName(builder);
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
|
@ -173,6 +202,7 @@ public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhr
|
|||
}
|
||||
matchQuery.setPhraseSlop(slop);
|
||||
matchQuery.setMaxExpansions(maxExpansions);
|
||||
matchQuery.setZeroTermsQuery(zeroTermsQuery);
|
||||
|
||||
return matchQuery.parse(MatchQuery.Type.PHRASE_PREFIX, fieldName, value);
|
||||
}
|
||||
|
@ -183,12 +213,13 @@ public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhr
|
|||
Objects.equals(value, other.value) &&
|
||||
Objects.equals(analyzer, other.analyzer)&&
|
||||
Objects.equals(slop, other.slop) &&
|
||||
Objects.equals(maxExpansions, other.maxExpansions);
|
||||
Objects.equals(maxExpansions, other.maxExpansions) &&
|
||||
Objects.equals(zeroTermsQuery, other.zeroTermsQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doHashCode() {
|
||||
return Objects.hash(fieldName, value, analyzer, slop, maxExpansions);
|
||||
return Objects.hash(fieldName, value, analyzer, slop, maxExpansions, zeroTermsQuery);
|
||||
}
|
||||
|
||||
public static MatchPhrasePrefixQueryBuilder fromXContent(XContentParser parser) throws IOException {
|
||||
|
@ -201,6 +232,7 @@ public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhr
|
|||
String queryName = null;
|
||||
XContentParser.Token token;
|
||||
String currentFieldName = null;
|
||||
ZeroTermsQuery zeroTermsQuery = MatchQuery.DEFAULT_ZERO_TERMS_QUERY;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
|
@ -223,6 +255,16 @@ public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhr
|
|||
maxExpansion = parser.intValue();
|
||||
} else if (AbstractQueryBuilder.NAME_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
queryName = parser.text();
|
||||
} else if (ZERO_TERMS_QUERY_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
|
||||
String zeroTermsValue = parser.text();
|
||||
if ("none".equalsIgnoreCase(zeroTermsValue)) {
|
||||
zeroTermsQuery = ZeroTermsQuery.NONE;
|
||||
} else if ("all".equalsIgnoreCase(zeroTermsValue)) {
|
||||
zeroTermsQuery = ZeroTermsQuery.ALL;
|
||||
} else {
|
||||
throw new ParsingException(parser.getTokenLocation(),
|
||||
"Unsupported zero_terms_query value [" + zeroTermsValue + "]");
|
||||
}
|
||||
} else {
|
||||
throw new ParsingException(parser.getTokenLocation(),
|
||||
"[" + NAME + "] query does not support [" + currentFieldName + "]");
|
||||
|
@ -245,6 +287,7 @@ public class MatchPhrasePrefixQueryBuilder extends AbstractQueryBuilder<MatchPhr
|
|||
matchQuery.maxExpansions(maxExpansion);
|
||||
matchQuery.queryName(queryName);
|
||||
matchQuery.boost(boost);
|
||||
matchQuery.zeroTermsQuery(zeroTermsQuery);
|
||||
return matchQuery;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,13 @@
|
|||
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.SynonymQuery;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
|
||||
import org.elasticsearch.index.search.MatchQuery.ZeroTermsQuery;
|
||||
import org.elasticsearch.test.AbstractQueryTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -33,6 +35,7 @@ import java.util.Map;
|
|||
import static org.hamcrest.CoreMatchers.either;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
public class MatchPhrasePrefixQueryBuilderTests extends AbstractQueryTestCase<MatchPhrasePrefixQueryBuilder> {
|
||||
|
@ -64,6 +67,9 @@ public class MatchPhrasePrefixQueryBuilderTests extends AbstractQueryTestCase<Ma
|
|||
if (randomBoolean()) {
|
||||
matchQuery.maxExpansions(randomIntBetween(1, 10000));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
matchQuery.zeroTermsQuery(randomFrom(ZeroTermsQuery.ALL, ZeroTermsQuery.NONE));
|
||||
}
|
||||
return matchQuery;
|
||||
}
|
||||
|
||||
|
@ -85,6 +91,12 @@ public class MatchPhrasePrefixQueryBuilderTests extends AbstractQueryTestCase<Ma
|
|||
protected void doAssertLuceneQuery(MatchPhrasePrefixQueryBuilder queryBuilder, Query query, QueryShardContext context)
|
||||
throws IOException {
|
||||
assertThat(query, notNullValue());
|
||||
|
||||
if (query instanceof MatchAllDocsQuery) {
|
||||
assertThat(queryBuilder.zeroTermsQuery(), equalTo(ZeroTermsQuery.ALL));
|
||||
return;
|
||||
}
|
||||
|
||||
assertThat(query, either(instanceOf(MultiPhrasePrefixQuery.class))
|
||||
.or(instanceOf(SynonymQuery.class))
|
||||
.or(instanceOf(MatchNoDocsQuery.class)));
|
||||
|
@ -115,6 +127,16 @@ public class MatchPhrasePrefixQueryBuilderTests extends AbstractQueryTestCase<Ma
|
|||
expectThrows(IllegalStateException.class, () -> matchQuery.doToQuery(createShardContext()));
|
||||
}
|
||||
|
||||
public void testPhrasePrefixZeroTermsQuery() throws IOException {
|
||||
MatchPhrasePrefixQueryBuilder matchQuery = new MatchPhrasePrefixQueryBuilder(TEXT_FIELD_NAME, "");
|
||||
matchQuery.zeroTermsQuery(ZeroTermsQuery.NONE);
|
||||
assertEquals(new MatchNoDocsQuery(), matchQuery.doToQuery(createShardContext()));
|
||||
|
||||
matchQuery = new MatchPhrasePrefixQueryBuilder(TEXT_FIELD_NAME, "");
|
||||
matchQuery.zeroTermsQuery(ZeroTermsQuery.ALL);
|
||||
assertEquals(new MatchAllDocsQuery(), matchQuery.doToQuery(createShardContext()));
|
||||
}
|
||||
|
||||
public void testPhrasePrefixMatchQuery() throws IOException {
|
||||
String json1 = "{\n" +
|
||||
" \"match_phrase_prefix\" : {\n" +
|
||||
|
@ -128,6 +150,7 @@ public class MatchPhrasePrefixQueryBuilderTests extends AbstractQueryTestCase<Ma
|
|||
" \"query\" : \"this is a test\",\n" +
|
||||
" \"slop\" : 0,\n" +
|
||||
" \"max_expansions\" : 50,\n" +
|
||||
" \"zero_terms_query\" : \"NONE\",\n" +
|
||||
" \"boost\" : 1.0\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
|
@ -149,6 +172,7 @@ public class MatchPhrasePrefixQueryBuilderTests extends AbstractQueryTestCase<Ma
|
|||
" \"query\" : \"this is a test\",\n" +
|
||||
" \"slop\" : 0,\n" +
|
||||
" \"max_expansions\" : 10,\n" +
|
||||
" \"zero_terms_query\" : \"NONE\",\n" +
|
||||
" \"boost\" : 1.0\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
|
|
Loading…
Reference in New Issue