Skip to content

Commit d6a2e01

Browse files
committed
Deprecate CommonTermsQuery and cutoff_frequency
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 also redundant. Relates to elastic#27096
1 parent e97bee6 commit d6a2e01

14 files changed

+114
-12
lines changed

docs/reference/query-dsl/common-terms-query.asciidoc

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
[[query-dsl-common-terms-query]]
22
=== Common Terms Query
33

4+
deprecated[7.3.0,Replaced by the more performant `max_score` optimization which is applied automatically without any configuration on a <<query-dsl-match-query>>]
5+
46
The `common` terms query is a modern alternative to stopwords which
57
improves the precision and recall of search results (by taking stopwords
68
into account), without sacrificing performance.

docs/reference/query-dsl/match-query.asciidoc

+2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ GET /_search
122122
[[query-dsl-match-query-cutoff]]
123123
===== Cutoff frequency
124124

125+
deprecated[7.3.0,Replaced by the more performant `max_score` optimization which is applied automatically without any configuration]
126+
125127
The match query supports a `cutoff_frequency` that allows
126128
specifying an absolute or relative document frequency where high
127129
frequency terms are moved into an optional subquery and are only scored

server/src/main/java/org/apache/lucene/queries/BlendedTermQuery.java

+5
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,11 @@ public int hashCode() {
278278
return Objects.hash(classHash(), Arrays.hashCode(equalsTerms()));
279279
}
280280

281+
/**
282+
* @deprecated Since max_score optimization landed in 7.0, normal MultiMatchQuery
283+
* will achieve the same result without any configuration.
284+
*/
285+
@Deprecated
281286
public static BlendedTermQuery commonTermsBlendedQuery(Term[] terms, final float[] boosts, final float maxTermFrequency) {
282287
return new BlendedTermQuery(terms, boosts) {
283288
@Override

server/src/main/java/org/apache/lucene/queries/ExtendedCommonTermsQuery.java

+4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@
2626
* Extended version of {@link CommonTermsQuery} that allows to pass in a
2727
* {@code minimumNumberShouldMatch} specification that uses the actual num of high frequent terms
2828
* to calculate the minimum matching terms.
29+
*
30+
* @deprecated Since max_optimization optimization landed in 7.0, normal MatchQuery
31+
* will achieve the same result without any configuration.
2932
*/
33+
@Deprecated
3034
public class ExtendedCommonTermsQuery extends CommonTermsQuery {
3135

3236
public ExtendedCommonTermsQuery(Occur highFreqOccur, Occur lowFreqOccur, float maxTermFrequency) {

server/src/main/java/org/elasticsearch/index/query/CommonTermsQueryBuilder.java

+4
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@
4747
* and high-frequency terms are added to an optional boolean clause. The
4848
* optional clause is only executed if the required "low-frequency' clause
4949
* matches.
50+
*
51+
* @deprecated Since max_optimization optimization landed in 7.0, normal MatchQuery
52+
* will achieve the same result without any configuration.
5053
*/
54+
@Deprecated
5155
public class CommonTermsQueryBuilder extends AbstractQueryBuilder<CommonTermsQueryBuilder> {
5256

5357
public static final String NAME = "common";

server/src/main/java/org/elasticsearch/index/query/MatchQueryBuilder.java

+23-1
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919

2020
package org.elasticsearch.index.query;
2121

22+
import org.apache.logging.log4j.LogManager;
2223
import org.apache.lucene.search.FuzzyQuery;
2324
import org.apache.lucene.search.Query;
2425
import org.elasticsearch.common.ParseField;
2526
import org.elasticsearch.common.ParsingException;
2627
import org.elasticsearch.common.io.stream.StreamInput;
2728
import org.elasticsearch.common.io.stream.StreamOutput;
29+
import org.elasticsearch.common.logging.DeprecationLogger;
2830
import org.elasticsearch.common.lucene.search.Queries;
2931
import org.elasticsearch.common.unit.Fuzziness;
3032
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
@@ -42,8 +44,20 @@
4244
* result of the analysis.
4345
*/
4446
public class MatchQueryBuilder extends AbstractQueryBuilder<MatchQueryBuilder> {
47+
48+
private static final DeprecationLogger deprecationLogger =
49+
new DeprecationLogger(LogManager.getLogger(MatchQueryBuilder.class));
50+
51+
static final String CUTOFF_FREQUENCY_DEPRECATION_MSG = "[cutoff_frequency] has been deprecated in favor of the " +
52+
"[max_score] optimization which is applied automatically without any configuration";
53+
4554
public static final ParseField ZERO_TERMS_QUERY_FIELD = new ParseField("zero_terms_query");
46-
public static final ParseField CUTOFF_FREQUENCY_FIELD = new ParseField("cutoff_frequency");
55+
/**
56+
* @deprecated Since max_optimization optimization landed in 7.0, normal MatchQuery
57+
* will achieve the same result without any configuration.
58+
*/
59+
@Deprecated
60+
public static final ParseField CUTOFF_FREQUENCY_FIELD = new ParseField("cutoff_frequency", "cutoff_frequency");
4761
public static final ParseField LENIENT_FIELD = new ParseField("lenient");
4862
public static final ParseField FUZZY_TRANSPOSITIONS_FIELD = new ParseField("fuzzy_transpositions");
4963
public static final ParseField FUZZY_REWRITE_FIELD = new ParseField("fuzzy_rewrite");
@@ -85,6 +99,10 @@ public class MatchQueryBuilder extends AbstractQueryBuilder<MatchQueryBuilder> {
8599

86100
private MatchQuery.ZeroTermsQuery zeroTermsQuery = MatchQuery.DEFAULT_ZERO_TERMS_QUERY;
87101

102+
/**
103+
* @deprecated See {@link MatchQueryBuilder#CUTOFF_FREQUENCY_FIELD} for more details
104+
*/
105+
@Deprecated
88106
private Float cutoffFrequency = null;
89107

90108
private boolean autoGenerateSynonymsPhraseQuery = true;
@@ -235,8 +253,12 @@ public int maxExpansions() {
235253
* Set a cutoff value in [0..1] (or absolute number &gt;=1) representing the
236254
* maximum threshold of a terms document frequency to be considered a low
237255
* frequency term.
256+
*
257+
* @deprecated see {@link MatchQueryBuilder#CUTOFF_FREQUENCY_FIELD} for more details
238258
*/
259+
@Deprecated
239260
public MatchQueryBuilder cutoffFrequency(float cutoff) {
261+
deprecationLogger.deprecated(CUTOFF_FREQUENCY_DEPRECATION_MSG);
240262
this.cutoffFrequency = cutoff;
241263
return this;
242264
}

server/src/main/java/org/elasticsearch/index/query/MultiMatchQueryBuilder.java

+28-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.index.query;
2121

22+
import org.apache.logging.log4j.LogManager;
2223
import org.apache.lucene.search.FuzzyQuery;
2324
import org.apache.lucene.search.Query;
2425
import org.elasticsearch.ElasticsearchParseException;
@@ -28,6 +29,7 @@
2829
import org.elasticsearch.common.io.stream.StreamInput;
2930
import org.elasticsearch.common.io.stream.StreamOutput;
3031
import org.elasticsearch.common.io.stream.Writeable;
32+
import org.elasticsearch.common.logging.DeprecationLogger;
3133
import org.elasticsearch.common.unit.Fuzziness;
3234
import org.elasticsearch.common.xcontent.DeprecationHandler;
3335
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
@@ -50,6 +52,13 @@
5052
* Same as {@link MatchQueryBuilder} but supports multiple fields.
5153
*/
5254
public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQueryBuilder> {
55+
56+
private static final DeprecationLogger deprecationLogger =
57+
new DeprecationLogger(LogManager.getLogger(MultiMatchQueryBuilder.class));
58+
59+
static final String CUTOFF_FREQUENCY_DEPRECATION_MSG = "[cutoff_frequency] has been deprecated in favor of the " +
60+
"[max_score] optimization which is applied automatically without any configuration";
61+
5362
public static final String NAME = "multi_match";
5463

5564
public static final MultiMatchQueryBuilder.Type DEFAULT_TYPE = MultiMatchQueryBuilder.Type.BEST_FIELDS;
@@ -63,7 +72,12 @@ public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQuery
6372
private static final ParseField SLOP_FIELD = new ParseField("slop");
6473
private static final ParseField ZERO_TERMS_QUERY_FIELD = new ParseField("zero_terms_query");
6574
private static final ParseField LENIENT_FIELD = new ParseField("lenient");
66-
private static final ParseField CUTOFF_FREQUENCY_FIELD = new ParseField("cutoff_frequency");
75+
/**
76+
* @deprecated Since max_score optimization landed in 7.0, normal MultiMatchQuery
77+
* will achieve the same result without any configuration.
78+
*/
79+
@Deprecated
80+
private static final ParseField CUTOFF_FREQUENCY_FIELD = new ParseField("cutoff_frequency", "cutoff_frequency");
6781
private static final ParseField TIE_BREAKER_FIELD = new ParseField("tie_breaker");
6882
private static final ParseField FUZZY_REWRITE_FIELD = new ParseField("fuzzy_rewrite");
6983
private static final ParseField MINIMUM_SHOULD_MATCH_FIELD = new ParseField("minimum_should_match");
@@ -91,6 +105,10 @@ public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQuery
91105
private String fuzzyRewrite = null;
92106
private Float tieBreaker;
93107
private Boolean lenient;
108+
/**
109+
* @deprecated See {@link MultiMatchQueryBuilder#CUTOFF_FREQUENCY_FIELD} for more details
110+
*/
111+
@Deprecated
94112
private Float cutoffFrequency = null;
95113
private MatchQuery.ZeroTermsQuery zeroTermsQuery = DEFAULT_ZERO_TERMS_QUERY;
96114
private boolean autoGenerateSynonymsPhraseQuery = true;
@@ -484,8 +502,11 @@ public boolean lenient() {
484502
* Set a cutoff value in [0..1] (or absolute number &gt;=1) representing the
485503
* maximum threshold of a terms document frequency to be considered a low
486504
* frequency term.
505+
* @deprecated See {@link MultiMatchQueryBuilder#CUTOFF_FREQUENCY_FIELD} for more details
487506
*/
507+
@Deprecated
488508
public MultiMatchQueryBuilder cutoffFrequency(float cutoff) {
509+
deprecationLogger.deprecated(CUTOFF_FREQUENCY_DEPRECATION_MSG);
489510
this.cutoffFrequency = cutoff;
490511
return this;
491512
}
@@ -494,8 +515,14 @@ public MultiMatchQueryBuilder cutoffFrequency(float cutoff) {
494515
* Set a cutoff value in [0..1] (or absolute number &gt;=1) representing the
495516
* maximum threshold of a terms document frequency to be considered a low
496517
* frequency term.
518+
*
519+
* @deprecated See {@link MultiMatchQueryBuilder#CUTOFF_FREQUENCY_FIELD} for more details
497520
*/
521+
@Deprecated
498522
public MultiMatchQueryBuilder cutoffFrequency(Float cutoff) {
523+
if (cutoff != null) {
524+
deprecationLogger.deprecated(CUTOFF_FREQUENCY_DEPRECATION_MSG);
525+
}
499526
this.cutoffFrequency = cutoff;
500527
return this;
501528
}

server/src/main/java/org/elasticsearch/index/query/QueryBuilders.java

+3
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ public static MatchQueryBuilder matchQuery(String name, Object text) {
6666
*
6767
* @param fieldName The field name.
6868
* @param text The query text (to be analyzed).
69+
*
70+
* @deprecated See {@link CommonTermsQueryBuilder}
6971
*/
72+
@Deprecated
7073
public static CommonTermsQueryBuilder commonTermsQuery(String fieldName, Object text) {
7174
return new CommonTermsQueryBuilder(fieldName, text);
7275
}

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

+17
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.elasticsearch.index.mapper.KeywordFieldMapper;
5656
import org.elasticsearch.index.mapper.MappedFieldType;
5757
import org.elasticsearch.index.mapper.TextFieldMapper;
58+
import org.elasticsearch.index.query.CommonTermsQueryBuilder;
5859
import org.elasticsearch.index.query.QueryShardContext;
5960
import org.elasticsearch.index.query.support.QueryParsers;
6061

@@ -171,6 +172,10 @@ public void writeTo(StreamOutput out) throws IOException {
171172

172173
protected ZeroTermsQuery zeroTermsQuery = DEFAULT_ZERO_TERMS_QUERY;
173174

175+
/**
176+
* @deprecated See {@link MatchQueryBuilder#setCommonTermsCutoff(Float)} for more details
177+
*/
178+
@Deprecated
174179
protected Float commonTermsCutoff = null;
175180

176181
protected boolean autoGenerateSynonymsPhraseQuery = true;
@@ -194,6 +199,10 @@ public void setOccur(BooleanClause.Occur occur) {
194199
this.occur = occur;
195200
}
196201

202+
/**
203+
* @deprecated See {@link MatchQueryBuilder#setCommonTermsCutoff(Float)} for more details
204+
*/
205+
@Deprecated
197206
public void setCommonTermsCutoff(Float cutoff) {
198207
this.commonTermsCutoff = cutoff;
199208
}
@@ -298,6 +307,10 @@ protected final Query parseInternal(Type type, String fieldName, MatchQueryBuild
298307
return query == null ? zeroTermsQuery() : query;
299308
}
300309

310+
/**
311+
* @deprecated See {@link CommonTermsQueryBuilder}
312+
*/
313+
@Deprecated
301314
private Query createCommonTermsQuery(MatchQueryBuilder builder, String field, String queryText,
302315
Occur highFreqOccur, Occur lowFreqOccur, float maxTermFrequency) {
303316
Query booleanQuery = builder.createBooleanQuery(field, queryText, lowFreqOccur);
@@ -308,6 +321,10 @@ private Query createCommonTermsQuery(MatchQueryBuilder builder, String field, St
308321
return booleanQuery;
309322
}
310323

324+
/**
325+
* @deprecated See {@link CommonTermsQueryBuilder}
326+
*/
327+
@Deprecated
311328
private Query boolToExtendedCommonTermsQuery(BooleanQuery bq,
312329
Occur highFreqOccur,
313330
Occur lowFreqOccur,

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

+4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
import static org.hamcrest.Matchers.instanceOf;
3838
import static org.hamcrest.Matchers.nullValue;
3939

40+
/**
41+
* @deprecated See {@link CommonTermsQueryBuilder}
42+
*/
43+
@Deprecated
4044
public class CommonTermsQueryBuilderTests extends AbstractQueryTestCase<CommonTermsQueryBuilder> {
4145

4246
@Override

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@
2222
import org.elasticsearch.action.search.SearchResponse;
2323
import org.elasticsearch.test.ESSingleNodeTestCase;
2424

25-
import java.io.IOException;
26-
25+
/**
26+
* @deprecated See {@link CommonTermsQueryBuilder}
27+
*/
28+
@Deprecated
2729
public class CommonTermsQueryParserTests extends ESSingleNodeTestCase {
28-
public void testWhenParsedQueryIsNullNoNullPointerExceptionIsThrown() throws IOException {
30+
public void testWhenParsedQueryIsNullNoNullPointerExceptionIsThrown() {
2931
final String index = "test-index";
3032
final String type = "test-type";
3133
client()

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

+5-4
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,6 @@ protected MatchQueryBuilder doCreateTestQueryBuilder() {
124124
matchQuery.zeroTermsQuery(randomFrom(ZeroTermsQuery.ALL, ZeroTermsQuery.NONE));
125125
}
126126

127-
if (randomBoolean()) {
128-
matchQuery.cutoffFrequency((float) 10 / randomIntBetween(1, 100));
129-
}
130-
131127
if (randomBoolean()) {
132128
matchQuery.autoGenerateSynonymsPhraseQuery(randomBoolean());
133129
}
@@ -478,6 +474,11 @@ public void testMaxBooleanClause() {
478474
query.setAnalyzer(new MockGraphAnalyzer(createGiantGraphMultiTerms()));
479475
expectThrows(BooleanQuery.TooManyClauses.class, () -> query.parse(Type.PHRASE, STRING_FIELD_NAME, ""));
480476
}
477+
478+
public void testCutoffFrequency() {
479+
new MatchQueryBuilder("field", "value").cutoffFrequency((float) 10 / randomIntBetween(1, 100));
480+
assertWarnings(MatchQueryBuilder.CUTOFF_FREQUENCY_DEPRECATION_MSG);
481+
}
481482

482483
private static class MockGraphAnalyzer extends Analyzer {
483484

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

+8-3
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,6 @@ protected MultiMatchQueryBuilder doCreateTestQueryBuilder() {
134134
if (randomBoolean()) {
135135
query.tieBreaker(randomFloat());
136136
}
137-
if (randomBoolean() && query.type() != Type.BOOL_PREFIX) {
138-
query.cutoffFrequency((float) 10 / randomIntBetween(1, 100));
139-
}
140137
if (randomBoolean()) {
141138
query.zeroTermsQuery(randomFrom(MatchQuery.ZeroTermsQuery.NONE, MatchQuery.ZeroTermsQuery.ALL));
142139
}
@@ -558,6 +555,14 @@ public void testNegativeFieldBoost() {
558555
assertThat(exc.getMessage(), containsString("negative [boost]"));
559556
}
560557

558+
public void testCutoffFrequency() {
559+
new MultiMatchQueryBuilder("value", "field1", "field2").cutoffFrequency(10f / randomIntBetween(1, 100));
560+
assertWarnings(MultiMatchQueryBuilder.CUTOFF_FREQUENCY_DEPRECATION_MSG);
561+
new MultiMatchQueryBuilder("value", "field1", "field2").cutoffFrequency(Float.valueOf(10f / randomIntBetween(1, 100)));
562+
assertWarnings(MultiMatchQueryBuilder.CUTOFF_FREQUENCY_DEPRECATION_MSG);
563+
564+
}
565+
561566
private static IndexMetaData newIndexMeta(String name, Settings oldIndexSettings, Settings indexSettings) {
562567
Settings build = Settings.builder().put(oldIndexSettings)
563568
.put(indexSettings)

server/src/test/java/org/elasticsearch/search/profile/query/RandomQueryGenerator.java

+4
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ private static QueryBuilder randomConstantScoreQuery(List<String> stringFields,
169169
return QueryBuilders.constantScoreQuery(randomQueryBuilder(stringFields, numericFields, numDocs, depth - 1));
170170
}
171171

172+
/**
173+
* @deprecated See {@link CommonTermsQueryBuilder}
174+
*/
175+
@Deprecated
172176
private static QueryBuilder randomCommonTermsQuery(List<String> fields, int numDocs) {
173177
int numTerms = randomInt(numDocs);
174178

0 commit comments

Comments
 (0)