Deprecate CommonTermsQuery and cutoff_frequency (#42619) (#42691)

Since the max_score optimization landed in Elasticsearch 7,
the CommonTermsQuery is redundant and slower. Moreover the
cutoff_frequency parameter for MatchQuery and MultiMatchQuery
is redundant.

Relates to #27096

(cherry picked from commit 04b74497314eeec076753a33b3b6cc11549646e8)
This commit is contained in:
Marios Trivyzas 2019-05-30 18:04:47 +02:00 committed by GitHub
parent ac8a9515a3
commit ce30afcd01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 145 additions and 50 deletions

View File

@ -1,6 +1,8 @@
[[query-dsl-common-terms-query]] [[query-dsl-common-terms-query]]
=== Common Terms Query === Common Terms Query
deprecated[7.3.0,"Use <<query-dsl-match-query>> instead, which skips blocks of documents efficiently, without any configuration, provided that the total number of hits is not tracked."]
The `common` terms query is a modern alternative to stopwords which The `common` terms query is a modern alternative to stopwords which
improves the precision and recall of search results (by taking stopwords improves the precision and recall of search results (by taking stopwords
into account), without sacrificing performance. into account), without sacrificing performance.
@ -83,6 +85,7 @@ GET /_search
} }
-------------------------------------------------- --------------------------------------------------
// CONSOLE // CONSOLE
// TEST[warning:Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]]
The number of terms which should match can be controlled with the The number of terms which should match can be controlled with the
<<query-dsl-minimum-should-match,`minimum_should_match`>> <<query-dsl-minimum-should-match,`minimum_should_match`>>
@ -108,6 +111,7 @@ GET /_search
} }
-------------------------------------------------- --------------------------------------------------
// CONSOLE // CONSOLE
// TEST[warning:Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]]
which is roughly equivalent to: which is roughly equivalent to:
@ -154,6 +158,7 @@ GET /_search
} }
-------------------------------------------------- --------------------------------------------------
// CONSOLE // CONSOLE
// TEST[warning:Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]]
which is roughly equivalent to: which is roughly equivalent to:
@ -209,6 +214,7 @@ GET /_search
} }
-------------------------------------------------- --------------------------------------------------
// CONSOLE // CONSOLE
// TEST[warning:Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]]
which is roughly equivalent to: which is roughly equivalent to:
@ -270,6 +276,7 @@ GET /_search
} }
-------------------------------------------------- --------------------------------------------------
// CONSOLE // CONSOLE
// TEST[warning:Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]]
which is roughly equivalent to: which is roughly equivalent to:

View File

@ -103,6 +103,8 @@ GET /_search
[[query-dsl-match-query-cutoff]] [[query-dsl-match-query-cutoff]]
===== Cutoff frequency ===== Cutoff frequency
deprecated[7.3.0,"This option can be omitted as the <<query-dsl-match-query>> can skip block of documents efficiently, without any configuration, provided that the total number of hits is not tracked."]
The match query supports a `cutoff_frequency` that allows The match query supports a `cutoff_frequency` that allows
specifying an absolute or relative document frequency where high specifying an absolute or relative document frequency where high
frequency terms are moved into an optional subquery and are only scored frequency terms are moved into an optional subquery and are only scored
@ -139,6 +141,7 @@ GET /_search
} }
-------------------------------------------------- --------------------------------------------------
// CONSOLE // CONSOLE
// TEST[warning:Deprecated field [cutoff_frequency] used, replaced by [you can omit this option, the [match] query can skip block of documents efficiently if the total number of hits is not tracked]]
IMPORTANT: The `cutoff_frequency` option operates on a per-shard-level. This means IMPORTANT: The `cutoff_frequency` option operates on a per-shard-level. This means
that when trying it out on test indexes with low document numbers you that when trying it out on test indexes with low document numbers you

View File

@ -1,5 +1,8 @@
--- ---
"Test common terms query with stacked tokens": "Test common terms query with stacked tokens":
- skip:
features: "warnings"
- do: - do:
indices.create: indices.create:
index: test index: test
@ -47,6 +50,8 @@
refresh: true refresh: true
- do: - do:
warnings:
- 'Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]'
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
body: body:
@ -62,6 +67,8 @@
- match: { hits.hits.2._id: "3" } - match: { hits.hits.2._id: "3" }
- do: - do:
warnings:
- 'Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]'
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
body: body:
@ -76,6 +83,8 @@
- match: { hits.hits.1._id: "2" } - match: { hits.hits.1._id: "2" }
- do: - do:
warnings:
- 'Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]'
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
body: body:
@ -90,6 +99,8 @@
- match: { hits.hits.2._id: "3" } - match: { hits.hits.2._id: "3" }
- do: - do:
warnings:
- 'Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]'
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
body: body:
@ -103,6 +114,8 @@
- match: { hits.hits.0._id: "2" } - match: { hits.hits.0._id: "2" }
- do: - do:
warnings:
- 'Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]'
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
body: body:
@ -118,6 +131,8 @@
- match: { hits.hits.1._id: "1" } - match: { hits.hits.1._id: "1" }
- do: - do:
warnings:
- 'Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]'
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
body: body:
@ -132,6 +147,8 @@
- match: { hits.hits.0._id: "2" } - match: { hits.hits.0._id: "2" }
- do: - do:
warnings:
- 'Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]'
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
body: body:
@ -144,6 +161,8 @@
- match: { hits.hits.0._id: "2" } - match: { hits.hits.0._id: "2" }
- do: - do:
warnings:
- 'Deprecated field [common] used, replaced by [[match] query which can efficiently skip blocks of documents if the total number of hits is not tracked]'
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
body: body:
@ -158,6 +177,8 @@
- match: { hits.hits.2._id: "3" } - match: { hits.hits.2._id: "3" }
- do: - do:
warnings:
- 'Deprecated field [cutoff_frequency] used, replaced by [you can omit this option, the [match] query can skip block of documents efficiently if the total number of hits is not tracked]'
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
body: body:
@ -172,6 +193,8 @@
- match: { hits.hits.1._id: "2" } - match: { hits.hits.1._id: "2" }
- do: - do:
warnings:
- 'Deprecated field [cutoff_frequency] used, replaced by [you can omit this option, the [match] query can skip block of documents efficiently if the total number of hits is not tracked]'
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
body: body:
@ -187,6 +210,8 @@
- match: { hits.hits.2._id: "3" } - match: { hits.hits.2._id: "3" }
- do: - do:
warnings:
- 'Deprecated field [cutoff_frequency] used, replaced by [you can omit this option, the [match] query can skip block of documents efficiently if the total number of hits is not tracked]'
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
body: body:
@ -201,6 +226,8 @@
- match: { hits.hits.1._id: "2" } - match: { hits.hits.1._id: "2" }
- do: - do:
warnings:
- 'Deprecated field [cutoff_frequency] used, replaced by [you can omit this option, the [multi_match] query can skip block of documents efficiently if the total number of hits is not tracked]'
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
body: body:

View File

@ -278,6 +278,11 @@ public abstract class BlendedTermQuery extends Query {
return Objects.hash(classHash(), Arrays.hashCode(equalsTerms())); return Objects.hash(classHash(), Arrays.hashCode(equalsTerms()));
} }
/**
* @deprecated Since max_score optimization landed in 7.0, normal MultiMatchQuery
* will achieve the same result without any configuration.
*/
@Deprecated
public static BlendedTermQuery commonTermsBlendedQuery(Term[] terms, final float[] boosts, final float maxTermFrequency) { public static BlendedTermQuery commonTermsBlendedQuery(Term[] terms, final float[] boosts, final float maxTermFrequency) {
return new BlendedTermQuery(terms, boosts) { return new BlendedTermQuery(terms, boosts) {
@Override @Override

View File

@ -26,7 +26,11 @@ import org.elasticsearch.common.lucene.search.Queries;
* Extended version of {@link CommonTermsQuery} that allows to pass in a * Extended version of {@link CommonTermsQuery} that allows to pass in a
* {@code minimumNumberShouldMatch} specification that uses the actual num of high frequent terms * {@code minimumNumberShouldMatch} specification that uses the actual num of high frequent terms
* to calculate the minimum matching terms. * to calculate the minimum matching terms.
*
* @deprecated Since max_optimization optimization landed in 7.0, normal MatchQuery
* will achieve the same result without any configuration.
*/ */
@Deprecated
public class ExtendedCommonTermsQuery extends CommonTermsQuery { public class ExtendedCommonTermsQuery extends CommonTermsQuery {
public ExtendedCommonTermsQuery(Occur highFreqOccur, Occur lowFreqOccur, float maxTermFrequency) { public ExtendedCommonTermsQuery(Occur highFreqOccur, Occur lowFreqOccur, float maxTermFrequency) {

View File

@ -48,9 +48,16 @@ import java.util.Objects;
* and high-frequency terms are added to an optional boolean clause. The * and high-frequency terms are added to an optional boolean clause. The
* optional clause is only executed if the required "low-frequency' clause * optional clause is only executed if the required "low-frequency' clause
* matches. * matches.
*
* @deprecated Since max_optimization optimization landed in 7.0, normal MatchQuery
* will achieve the same result without any configuration.
*/ */
@Deprecated
public class CommonTermsQueryBuilder extends AbstractQueryBuilder<CommonTermsQueryBuilder> { public class CommonTermsQueryBuilder extends AbstractQueryBuilder<CommonTermsQueryBuilder> {
public static final String COMMON_TERMS_QUERY_DEPRECATION_MSG = "[match] query which can efficiently " +
"skip blocks of documents if the total number of hits is not tracked";
public static final String NAME = "common"; public static final String NAME = "common";
public static final float DEFAULT_CUTOFF_FREQ = 0.01f; public static final float DEFAULT_CUTOFF_FREQ = 0.01f;
@ -87,7 +94,9 @@ public class CommonTermsQueryBuilder extends AbstractQueryBuilder<CommonTermsQue
/** /**
* Constructs a new common terms query. * Constructs a new common terms query.
* @deprecated See {@link CommonTermsQueryBuilder} for more details.
*/ */
@Deprecated
public CommonTermsQueryBuilder(String fieldName, Object text) { public CommonTermsQueryBuilder(String fieldName, Object text) {
if (Strings.isEmpty(fieldName)) { if (Strings.isEmpty(fieldName)) {
throw new IllegalArgumentException("field name is null or empty"); throw new IllegalArgumentException("field name is null or empty");
@ -101,7 +110,9 @@ public class CommonTermsQueryBuilder extends AbstractQueryBuilder<CommonTermsQue
/** /**
* Read from a stream. * Read from a stream.
* @deprecated See {@link CommonTermsQueryBuilder} for more details.
*/ */
@Deprecated
public CommonTermsQueryBuilder(StreamInput in) throws IOException { public CommonTermsQueryBuilder(StreamInput in) throws IOException {
super(in); super(in);
fieldName = in.readString(); fieldName = in.readString();

View File

@ -43,8 +43,18 @@ import java.util.Objects;
* result of the analysis. * result of the analysis.
*/ */
public class MatchQueryBuilder extends AbstractQueryBuilder<MatchQueryBuilder> { public class MatchQueryBuilder extends AbstractQueryBuilder<MatchQueryBuilder> {
private static final String CUTOFF_FREQUENCY_DEPRECATION_MSG = "you can omit this option, " +
"the [match] query can skip block of documents efficiently if the total number of hits is not tracked";
public static final ParseField ZERO_TERMS_QUERY_FIELD = new ParseField("zero_terms_query"); public static final ParseField ZERO_TERMS_QUERY_FIELD = new ParseField("zero_terms_query");
public static final ParseField CUTOFF_FREQUENCY_FIELD = new ParseField("cutoff_frequency"); /**
* @deprecated Since max_optimization optimization landed in 7.0, normal MatchQuery
* will achieve the same result without any configuration.
*/
@Deprecated
public static final ParseField CUTOFF_FREQUENCY_FIELD =
new ParseField("cutoff_frequency").withAllDeprecated(CUTOFF_FREQUENCY_DEPRECATION_MSG);
public static final ParseField LENIENT_FIELD = new ParseField("lenient"); public static final ParseField LENIENT_FIELD = new ParseField("lenient");
public static final ParseField FUZZY_TRANSPOSITIONS_FIELD = new ParseField("fuzzy_transpositions"); public static final ParseField FUZZY_TRANSPOSITIONS_FIELD = new ParseField("fuzzy_transpositions");
public static final ParseField FUZZY_REWRITE_FIELD = new ParseField("fuzzy_rewrite"); public static final ParseField FUZZY_REWRITE_FIELD = new ParseField("fuzzy_rewrite");
@ -252,7 +262,10 @@ public class MatchQueryBuilder extends AbstractQueryBuilder<MatchQueryBuilder> {
* Set a cutoff value in [0..1] (or absolute number &gt;=1) representing the * Set a cutoff value in [0..1] (or absolute number &gt;=1) representing the
* maximum threshold of a terms document frequency to be considered a low * maximum threshold of a terms document frequency to be considered a low
* frequency term. * frequency term.
*
* @deprecated see {@link MatchQueryBuilder#CUTOFF_FREQUENCY_FIELD} for more details
*/ */
@Deprecated
public MatchQueryBuilder cutoffFrequency(float cutoff) { public MatchQueryBuilder cutoffFrequency(float cutoff) {
this.cutoffFrequency = cutoff; this.cutoffFrequency = cutoff;
return this; return this;

View File

@ -51,6 +51,10 @@ import java.util.TreeMap;
* Same as {@link MatchQueryBuilder} but supports multiple fields. * Same as {@link MatchQueryBuilder} but supports multiple fields.
*/ */
public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQueryBuilder> { public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQueryBuilder> {
private static final String CUTOFF_FREQUENCY_DEPRECATION_MSG = "you can omit this option, " +
"the [multi_match] query can skip block of documents efficiently if the total number of hits is not tracked";
public static final String NAME = "multi_match"; public static final String NAME = "multi_match";
public static final MultiMatchQueryBuilder.Type DEFAULT_TYPE = MultiMatchQueryBuilder.Type.BEST_FIELDS; public static final MultiMatchQueryBuilder.Type DEFAULT_TYPE = MultiMatchQueryBuilder.Type.BEST_FIELDS;
@ -64,7 +68,8 @@ public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQuery
private static final ParseField SLOP_FIELD = new ParseField("slop"); private static final ParseField SLOP_FIELD = new ParseField("slop");
private static final ParseField ZERO_TERMS_QUERY_FIELD = new ParseField("zero_terms_query"); private static final ParseField ZERO_TERMS_QUERY_FIELD = new ParseField("zero_terms_query");
private static final ParseField LENIENT_FIELD = new ParseField("lenient"); private static final ParseField LENIENT_FIELD = new ParseField("lenient");
private static final ParseField CUTOFF_FREQUENCY_FIELD = new ParseField("cutoff_frequency"); private static final ParseField CUTOFF_FREQUENCY_FIELD =
new ParseField("cutoff_frequency").withAllDeprecated(CUTOFF_FREQUENCY_DEPRECATION_MSG);
private static final ParseField TIE_BREAKER_FIELD = new ParseField("tie_breaker"); private static final ParseField TIE_BREAKER_FIELD = new ParseField("tie_breaker");
private static final ParseField FUZZY_REWRITE_FIELD = new ParseField("fuzzy_rewrite"); private static final ParseField FUZZY_REWRITE_FIELD = new ParseField("fuzzy_rewrite");
private static final ParseField MINIMUM_SHOULD_MATCH_FIELD = new ParseField("minimum_should_match"); private static final ParseField MINIMUM_SHOULD_MATCH_FIELD = new ParseField("minimum_should_match");
@ -505,7 +510,11 @@ public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQuery
* Set a cutoff value in [0..1] (or absolute number &gt;=1) representing the * Set a cutoff value in [0..1] (or absolute number &gt;=1) representing the
* maximum threshold of a terms document frequency to be considered a low * maximum threshold of a terms document frequency to be considered a low
* frequency term. * frequency term.
*
* @deprecated Since max_score optimization landed in 7.0, normal MultiMatchQuery
* will achieve the same result without any configuration.
*/ */
@Deprecated
public MultiMatchQueryBuilder cutoffFrequency(float cutoff) { public MultiMatchQueryBuilder cutoffFrequency(float cutoff) {
this.cutoffFrequency = cutoff; this.cutoffFrequency = cutoff;
return this; return this;
@ -515,7 +524,11 @@ public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQuery
* Set a cutoff value in [0..1] (or absolute number &gt;=1) representing the * Set a cutoff value in [0..1] (or absolute number &gt;=1) representing the
* maximum threshold of a terms document frequency to be considered a low * maximum threshold of a terms document frequency to be considered a low
* frequency term. * frequency term.
*
* @deprecated Since max_score optimization landed in 7.0, normal MultiMatchQuery
* will achieve the same result without any configuration.
*/ */
@Deprecated
public MultiMatchQueryBuilder cutoffFrequency(Float cutoff) { public MultiMatchQueryBuilder cutoffFrequency(Float cutoff) {
this.cutoffFrequency = cutoff; this.cutoffFrequency = cutoff;
return this; return this;

View File

@ -66,7 +66,10 @@ public final class QueryBuilders {
* *
* @param fieldName The field name. * @param fieldName The field name.
* @param text The query text (to be analyzed). * @param text The query text (to be analyzed).
*
* @deprecated See {@link CommonTermsQueryBuilder}
*/ */
@Deprecated
public static CommonTermsQueryBuilder commonTermsQuery(String fieldName, Object text) { public static CommonTermsQueryBuilder commonTermsQuery(String fieldName, Object text) {
return new CommonTermsQueryBuilder(fieldName, text); return new CommonTermsQueryBuilder(fieldName, text);
} }

View File

@ -194,6 +194,10 @@ public class MatchQuery {
this.occur = occur; this.occur = occur;
} }
/**
* @deprecated See {@link MatchQueryBuilder#setCommonTermsCutoff(Float)} for more details
*/
@Deprecated
public void setCommonTermsCutoff(Float cutoff) { public void setCommonTermsCutoff(Float cutoff) {
this.commonTermsCutoff = cutoff; this.commonTermsCutoff = cutoff;
} }

View File

@ -21,6 +21,7 @@ package org.elasticsearch.search;
import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.BooleanQuery;
import org.elasticsearch.common.NamedRegistry; import org.elasticsearch.common.NamedRegistry;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.geo.GeoShapeType; import org.elasticsearch.common.geo.GeoShapeType;
import org.elasticsearch.common.geo.ShapesAvailability; import org.elasticsearch.common.geo.ShapesAvailability;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
@ -32,7 +33,6 @@ import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.ParseFieldRegistry; import org.elasticsearch.common.xcontent.ParseFieldRegistry;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchBoolPrefixQueryBuilder;
import org.elasticsearch.index.query.BoostingQueryBuilder; import org.elasticsearch.index.query.BoostingQueryBuilder;
import org.elasticsearch.index.query.CommonTermsQueryBuilder; import org.elasticsearch.index.query.CommonTermsQueryBuilder;
import org.elasticsearch.index.query.ConstantScoreQueryBuilder; import org.elasticsearch.index.query.ConstantScoreQueryBuilder;
@ -49,6 +49,7 @@ import org.elasticsearch.index.query.IdsQueryBuilder;
import org.elasticsearch.index.query.IntervalQueryBuilder; import org.elasticsearch.index.query.IntervalQueryBuilder;
import org.elasticsearch.index.query.IntervalsSourceProvider; import org.elasticsearch.index.query.IntervalsSourceProvider;
import org.elasticsearch.index.query.MatchAllQueryBuilder; import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.MatchBoolPrefixQueryBuilder;
import org.elasticsearch.index.query.MatchNoneQueryBuilder; import org.elasticsearch.index.query.MatchNoneQueryBuilder;
import org.elasticsearch.index.query.MatchPhrasePrefixQueryBuilder; import org.elasticsearch.index.query.MatchPhrasePrefixQueryBuilder;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder; import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
@ -279,6 +280,7 @@ import java.util.function.Function;
import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableMap;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
import static org.elasticsearch.index.query.CommonTermsQueryBuilder.COMMON_TERMS_QUERY_DEPRECATION_MSG;
import static org.elasticsearch.index.query.SpanNearQueryBuilder.SpanGapQueryBuilder; import static org.elasticsearch.index.query.SpanNearQueryBuilder.SpanGapQueryBuilder;
/** /**
@ -807,7 +809,8 @@ public class SearchModule {
registerQuery(new QuerySpec<>(MoreLikeThisQueryBuilder.NAME, MoreLikeThisQueryBuilder::new, registerQuery(new QuerySpec<>(MoreLikeThisQueryBuilder.NAME, MoreLikeThisQueryBuilder::new,
MoreLikeThisQueryBuilder::fromXContent)); MoreLikeThisQueryBuilder::fromXContent));
registerQuery(new QuerySpec<>(WrapperQueryBuilder.NAME, WrapperQueryBuilder::new, WrapperQueryBuilder::fromXContent)); registerQuery(new QuerySpec<>(WrapperQueryBuilder.NAME, WrapperQueryBuilder::new, WrapperQueryBuilder::fromXContent));
registerQuery(new QuerySpec<>(CommonTermsQueryBuilder.NAME, CommonTermsQueryBuilder::new, CommonTermsQueryBuilder::fromXContent)); registerQuery(new QuerySpec<>(new ParseField(CommonTermsQueryBuilder.NAME).withAllDeprecated(COMMON_TERMS_QUERY_DEPRECATION_MSG),
CommonTermsQueryBuilder::new, CommonTermsQueryBuilder::fromXContent));
registerQuery( registerQuery(
new QuerySpec<>(SpanMultiTermQueryBuilder.NAME, SpanMultiTermQueryBuilder::new, SpanMultiTermQueryBuilder::fromXContent)); new QuerySpec<>(SpanMultiTermQueryBuilder.NAME, SpanMultiTermQueryBuilder::new, SpanMultiTermQueryBuilder::fromXContent));
registerQuery(new QuerySpec<>(FunctionScoreQueryBuilder.NAME, FunctionScoreQueryBuilder::new, registerQuery(new QuerySpec<>(FunctionScoreQueryBuilder.NAME, FunctionScoreQueryBuilder::new,

View File

@ -111,6 +111,30 @@ public class CommonTermsQueryBuilderTests extends AbstractQueryTestCase<CommonTe
assertThat(extendedCommonTermsQuery.getLowFreqMinimumNumberShouldMatchSpec(), equalTo(queryBuilder.lowFreqMinimumShouldMatch())); assertThat(extendedCommonTermsQuery.getLowFreqMinimumNumberShouldMatchSpec(), equalTo(queryBuilder.lowFreqMinimumShouldMatch()));
} }
@Override
public void testUnknownField() throws IOException {
super.testUnknownField();
assertDeprecationWarning();
}
@Override
public void testUnknownObjectException() throws IOException {
super.testUnknownObjectException();
assertDeprecationWarning();
}
@Override
public void testFromXContent() throws IOException {
super.testFromXContent();
assertDeprecationWarning();
}
@Override
public void testValidOutput() throws IOException {
super.testValidOutput();
assertDeprecationWarning();
}
public void testIllegalArguments() { public void testIllegalArguments() {
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> new CommonTermsQueryBuilder(null, "text")); IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> new CommonTermsQueryBuilder(null, "text"));
assertEquals("field name is null or empty", e.getMessage()); assertEquals("field name is null or empty", e.getMessage());
@ -146,6 +170,8 @@ public class CommonTermsQueryBuilderTests extends AbstractQueryTestCase<CommonTe
assertEquals(query, Operator.OR, queryBuilder.lowFreqOperator()); assertEquals(query, Operator.OR, queryBuilder.lowFreqOperator());
assertEquals(query, Operator.AND, queryBuilder.highFreqOperator()); assertEquals(query, Operator.AND, queryBuilder.highFreqOperator());
assertEquals(query, "nelly the elephant not as a cartoon", queryBuilder.value()); assertEquals(query, "nelly the elephant not as a cartoon", queryBuilder.value());
assertDeprecationWarning();
} }
public void testCommonTermsQuery1() throws IOException { public void testCommonTermsQuery1() throws IOException {
@ -155,6 +181,8 @@ public class CommonTermsQueryBuilderTests extends AbstractQueryTestCase<CommonTe
ExtendedCommonTermsQuery ectQuery = (ExtendedCommonTermsQuery) parsedQuery; ExtendedCommonTermsQuery ectQuery = (ExtendedCommonTermsQuery) parsedQuery;
assertThat(ectQuery.getHighFreqMinimumNumberShouldMatchSpec(), nullValue()); assertThat(ectQuery.getHighFreqMinimumNumberShouldMatchSpec(), nullValue());
assertThat(ectQuery.getLowFreqMinimumNumberShouldMatchSpec(), equalTo("2")); assertThat(ectQuery.getLowFreqMinimumNumberShouldMatchSpec(), equalTo("2"));
assertDeprecationWarning();
} }
public void testCommonTermsQuery2() throws IOException { public void testCommonTermsQuery2() throws IOException {
@ -164,6 +192,8 @@ public class CommonTermsQueryBuilderTests extends AbstractQueryTestCase<CommonTe
ExtendedCommonTermsQuery ectQuery = (ExtendedCommonTermsQuery) parsedQuery; ExtendedCommonTermsQuery ectQuery = (ExtendedCommonTermsQuery) parsedQuery;
assertThat(ectQuery.getHighFreqMinimumNumberShouldMatchSpec(), equalTo("50%")); assertThat(ectQuery.getHighFreqMinimumNumberShouldMatchSpec(), equalTo("50%"));
assertThat(ectQuery.getLowFreqMinimumNumberShouldMatchSpec(), equalTo("5<20%")); assertThat(ectQuery.getLowFreqMinimumNumberShouldMatchSpec(), equalTo("5<20%"));
assertDeprecationWarning();
} }
public void testCommonTermsQuery3() throws IOException { public void testCommonTermsQuery3() throws IOException {
@ -173,12 +203,16 @@ public class CommonTermsQueryBuilderTests extends AbstractQueryTestCase<CommonTe
ExtendedCommonTermsQuery ectQuery = (ExtendedCommonTermsQuery) parsedQuery; ExtendedCommonTermsQuery ectQuery = (ExtendedCommonTermsQuery) parsedQuery;
assertThat(ectQuery.getHighFreqMinimumNumberShouldMatchSpec(), nullValue()); assertThat(ectQuery.getHighFreqMinimumNumberShouldMatchSpec(), nullValue());
assertThat(ectQuery.getLowFreqMinimumNumberShouldMatchSpec(), equalTo("2")); assertThat(ectQuery.getLowFreqMinimumNumberShouldMatchSpec(), equalTo("2"));
assertDeprecationWarning();
} }
// see #11730 // see #11730
public void testCommonTermsQuery4() throws IOException { public void testCommonTermsQuery4() throws IOException {
Query parsedQuery = parseQuery(commonTermsQuery("field", "text")).toQuery(createShardContext()); Query parsedQuery = parseQuery(commonTermsQuery("field", "text")).toQuery(createShardContext());
assertThat(parsedQuery, instanceOf(ExtendedCommonTermsQuery.class)); assertThat(parsedQuery, instanceOf(ExtendedCommonTermsQuery.class));
assertDeprecationWarning();
} }
public void testParseFailsWithMultipleFields() throws IOException { public void testParseFailsWithMultipleFields() throws IOException {
@ -204,5 +238,11 @@ public class CommonTermsQueryBuilderTests extends AbstractQueryTestCase<CommonTe
"}"; "}";
e = expectThrows(ParsingException.class, () -> parseQuery(shortJson)); e = expectThrows(ParsingException.class, () -> parseQuery(shortJson));
assertEquals("[common] query doesn't support multiple fields, found [message1] and [message2]", e.getMessage()); assertEquals("[common] query doesn't support multiple fields, found [message1] and [message2]", e.getMessage());
assertDeprecationWarning();
}
private void assertDeprecationWarning() {
assertWarnings("Deprecated field [common] used, replaced by [" + CommonTermsQueryBuilder.COMMON_TERMS_QUERY_DEPRECATION_MSG + "]");
} }
} }

View File

@ -22,10 +22,8 @@ package org.elasticsearch.index.query;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.test.ESSingleNodeTestCase; import org.elasticsearch.test.ESSingleNodeTestCase;
import java.io.IOException;
public class CommonTermsQueryParserTests extends ESSingleNodeTestCase { public class CommonTermsQueryParserTests extends ESSingleNodeTestCase {
public void testWhenParsedQueryIsNullNoNullPointerExceptionIsThrown() throws IOException { public void testWhenParsedQueryIsNullNoNullPointerExceptionIsThrown() {
final String index = "test-index"; final String index = "test-index";
final String type = "test-type"; final String type = "test-type";
client() client()

View File

@ -124,10 +124,6 @@ public class MatchQueryBuilderTests extends FullTextQueryTestCase<MatchQueryBuil
matchQuery.zeroTermsQuery(randomFrom(ZeroTermsQuery.ALL, ZeroTermsQuery.NONE)); matchQuery.zeroTermsQuery(randomFrom(ZeroTermsQuery.ALL, ZeroTermsQuery.NONE));
} }
if (randomBoolean()) {
matchQuery.cutoffFrequency((float) 10 / randomIntBetween(1, 100));
}
if (randomBoolean()) { if (randomBoolean()) {
matchQuery.autoGenerateSynonymsPhraseQuery(randomBoolean()); matchQuery.autoGenerateSynonymsPhraseQuery(randomBoolean());
} }

View File

@ -134,9 +134,6 @@ public class MultiMatchQueryBuilderTests extends FullTextQueryTestCase<MultiMatc
if (randomBoolean()) { if (randomBoolean()) {
query.tieBreaker(randomFloat()); query.tieBreaker(randomFloat());
} }
if (randomBoolean() && query.type() != Type.BOOL_PREFIX) {
query.cutoffFrequency((float) 10 / randomIntBetween(1, 100));
}
if (randomBoolean()) { if (randomBoolean()) {
query.zeroTermsQuery(randomFrom(MatchQuery.ZeroTermsQuery.NONE, MatchQuery.ZeroTermsQuery.ALL)); query.zeroTermsQuery(randomFrom(MatchQuery.ZeroTermsQuery.NONE, MatchQuery.ZeroTermsQuery.ALL));
} }

View File

@ -246,7 +246,7 @@ public class SearchModuleTests extends ESTestCase {
assertSame(highlighters.get("custom"), customHighlighter); assertSame(highlighters.get("custom"), customHighlighter);
} }
public void testRegisteredQueries() throws IOException { public void testRegisteredQueries() {
List<String> allSupportedQueries = new ArrayList<>(); List<String> allSupportedQueries = new ArrayList<>();
Collections.addAll(allSupportedQueries, NON_DEPRECATED_QUERIES); Collections.addAll(allSupportedQueries, NON_DEPRECATED_QUERIES);
Collections.addAll(allSupportedQueries, DEPRECATED_QUERIES); Collections.addAll(allSupportedQueries, DEPRECATED_QUERIES);
@ -254,6 +254,7 @@ public class SearchModuleTests extends ESTestCase {
Set<String> registeredNonDeprecated = module.getNamedXContents().stream() Set<String> registeredNonDeprecated = module.getNamedXContents().stream()
.filter(e -> e.categoryClass.equals(QueryBuilder.class)) .filter(e -> e.categoryClass.equals(QueryBuilder.class))
.filter(e -> e.name.getDeprecatedNames().length == 0)
.map(e -> e.name.getPreferredName()) .map(e -> e.name.getPreferredName())
.collect(toSet()); .collect(toSet());
Set<String> registeredAll = module.getNamedXContents().stream() Set<String> registeredAll = module.getNamedXContents().stream()
@ -316,7 +317,6 @@ public class SearchModuleTests extends ESTestCase {
private static final String[] NON_DEPRECATED_QUERIES = new String[] { private static final String[] NON_DEPRECATED_QUERIES = new String[] {
"bool", "bool",
"boosting", "boosting",
"common",
"constant_score", "constant_score",
"dis_max", "dis_max",
"exists", "exists",
@ -364,7 +364,7 @@ public class SearchModuleTests extends ESTestCase {
}; };
//add here deprecated queries to make sure we log a deprecation warnings when they are used //add here deprecated queries to make sure we log a deprecation warnings when they are used
private static final String[] DEPRECATED_QUERIES = new String[] {}; private static final String[] DEPRECATED_QUERIES = new String[] {"common"};
/** /**
* Dummy test {@link AggregationBuilder} used to test registering aggregation builders. * Dummy test {@link AggregationBuilder} used to test registering aggregation builders.

View File

@ -22,11 +22,9 @@ package org.elasticsearch.search.profile.query;
import org.apache.lucene.util.English; import org.apache.lucene.util.English;
import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.CommonTermsQueryBuilder;
import org.elasticsearch.index.query.DisMaxQueryBuilder; import org.elasticsearch.index.query.DisMaxQueryBuilder;
import org.elasticsearch.index.query.FuzzyQueryBuilder; import org.elasticsearch.index.query.FuzzyQueryBuilder;
import org.elasticsearch.index.query.IdsQueryBuilder; import org.elasticsearch.index.query.IdsQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder; import org.elasticsearch.index.query.RangeQueryBuilder;
@ -72,7 +70,7 @@ public class RandomQueryGenerator {
} }
private static QueryBuilder randomTerminalQuery(List<String> stringFields, List<String> numericFields, int numDocs) { private static QueryBuilder randomTerminalQuery(List<String> stringFields, List<String> numericFields, int numDocs) {
switch (randomIntBetween(0,6)) { switch (randomIntBetween(0,5)) {
case 0: case 0:
return randomTermQuery(stringFields, numDocs); return randomTermQuery(stringFields, numDocs);
case 1: case 1:
@ -82,10 +80,8 @@ public class RandomQueryGenerator {
case 3: case 3:
return QueryBuilders.matchAllQuery(); return QueryBuilders.matchAllQuery();
case 4: case 4:
return randomCommonTermsQuery(stringFields, numDocs);
case 5:
return randomFuzzyQuery(stringFields); return randomFuzzyQuery(stringFields);
case 6: case 5:
return randomIDsQuery(); return randomIDsQuery();
default: default:
return randomTermQuery(stringFields, numDocs); return randomTermQuery(stringFields, numDocs);
@ -169,31 +165,6 @@ public class RandomQueryGenerator {
return QueryBuilders.constantScoreQuery(randomQueryBuilder(stringFields, numericFields, numDocs, depth - 1)); return QueryBuilders.constantScoreQuery(randomQueryBuilder(stringFields, numericFields, numDocs, depth - 1));
} }
private static QueryBuilder randomCommonTermsQuery(List<String> fields, int numDocs) {
int numTerms = randomInt(numDocs);
QueryBuilder q = QueryBuilders.commonTermsQuery(randomField(fields), randomQueryString(numTerms));
if (randomBoolean()) {
((CommonTermsQueryBuilder)q).boost(randomFloat());
}
if (randomBoolean()) {
((CommonTermsQueryBuilder)q).cutoffFrequency(randomFloat());
}
if (randomBoolean()) {
((CommonTermsQueryBuilder)q).highFreqMinimumShouldMatch(Integer.toString(randomInt(numTerms)))
.highFreqOperator(randomBoolean() ? Operator.AND : Operator.OR);
}
if (randomBoolean()) {
((CommonTermsQueryBuilder)q).lowFreqMinimumShouldMatch(Integer.toString(randomInt(numTerms)))
.lowFreqOperator(randomBoolean() ? Operator.AND : Operator.OR);
}
return q;
}
private static QueryBuilder randomFuzzyQuery(List<String> fields) { private static QueryBuilder randomFuzzyQuery(List<String> fields) {
QueryBuilder q = QueryBuilders.fuzzyQuery(randomField(fields), randomQueryString(1)); QueryBuilder q = QueryBuilders.fuzzyQuery(randomField(fields), randomQueryString(1));

View File

@ -164,7 +164,7 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
* parse exception. Some specific objects do not cause any exception as they can hold arbitrary content; they can be * parse exception. Some specific objects do not cause any exception as they can hold arbitrary content; they can be
* declared by overriding {@link #getObjectsHoldingArbitraryContent()}. * declared by overriding {@link #getObjectsHoldingArbitraryContent()}.
*/ */
public final void testUnknownObjectException() throws IOException { public void testUnknownObjectException() throws IOException {
Set<String> candidates = new HashSet<>(); Set<String> candidates = new HashSet<>();
// Adds the valid query to the list of queries to modify and test // Adds the valid query to the list of queries to modify and test
candidates.add(createTestQueryBuilder().toString()); candidates.add(createTestQueryBuilder().toString());