Skip to content

Commit 51791f9

Browse files
authored
Deprecate negative field boosts in analyzed queries (#38176)
This change forbids negative field boost in the `query_string`, `simple_query_string` and `multi_match` queries. Negative boosts are not allowed in Lucene 8 (scores must be positive). The backport of this change to 6x will turn the error into a deprecation warning in order to raise the awareness of this breaking change in 7.0. Closes #33309
1 parent 3a40fb1 commit 51791f9

File tree

10 files changed

+64
-14
lines changed

10 files changed

+64
-14
lines changed

docs/reference/migration/migrate_6_0/search.asciidoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,10 @@ information.
153153
[float]
154154
===== Negative scores are deprecated in Function Score Query
155155

156-
Negative scores in the Function Score Query are deprecated. If a negative
156+
Negative scores in the Function Score Query are deprecated. If a negative
157157
score is produced as a result of computation (e.g. in `script_score` or
158158
`field_value_factor` functions), a deprecation warning will be issued in
159-
this major version, and an error will be thrown in the next major version.
159+
this major version, and an error will be thrown in the next major version.
160160

161161
[float]
162162
==== Fielddata on `_uid`
@@ -266,8 +266,8 @@ rewrite any prefix query on the field to a a single term query that matches the
266266
[float]
267267
==== Negative boosts are deprecated
268268

269-
Setting a negative `boost` in a query is deprecated and will throw an error in the next version.
270-
To deboost a specific query you can use a `boost` comprise between 0 and 1.
269+
Setting a negative `boost` for a query or a field is deprecated and will throw an error in the next
270+
major version. To deboost a specific query or field you can use a `boost` comprise between 0 and 1.
271271

272272
[float]
273273
==== Limit the number of open scroll contexts

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ protected AbstractQueryBuilder() {
7070

7171
protected AbstractQueryBuilder(StreamInput in) throws IOException {
7272
boost = in.readFloat();
73+
checkNegativeBoost(boost);
7374
queryName = in.readOptionalString();
7475
}
7576

@@ -158,17 +159,21 @@ public final float boost() {
158159
return this.boost;
159160
}
160161

162+
protected final void checkNegativeBoost(float boost) {
163+
if (Float.compare(boost, 0f) < 0) {
164+
deprecationLogger.deprecatedAndMaybeLog("negative boost", "setting a negative [boost] on a query " +
165+
"is deprecated and will throw an error in the next major version. You can use a value between 0 and 1 to deboost.");
166+
}
167+
}
168+
161169
/**
162170
* Sets the boost for this query. Documents matching this query will (in addition to the normal
163171
* weightings) have their score multiplied by the boost provided.
164172
*/
165173
@SuppressWarnings("unchecked")
166174
@Override
167175
public final QB boost(float boost) {
168-
if (Float.compare(boost, 0f) < 0) {
169-
deprecationLogger.deprecatedAndMaybeLog("negative boost", "setting a negative [boost] on a query " +
170-
"is deprecated and will throw an error in the next version. You can use a value between 0 and 1 to deboost.");
171-
}
176+
checkNegativeBoost(boost);
172177
this.boost = boost;
173178
return (QB) this;
174179
}

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,10 @@ public MultiMatchQueryBuilder(StreamInput in) throws IOException {
213213
int size = in.readVInt();
214214
fieldsBoosts = new TreeMap<>();
215215
for (int i = 0; i < size; i++) {
216-
fieldsBoosts.put(in.readString(), in.readFloat());
216+
String field = in.readString();
217+
float boost = in.readFloat();
218+
checkNegativeBoost(boost);
219+
fieldsBoosts.put(field, boost);
217220
}
218221
type = Type.readFromStream(in);
219222
operator = Operator.readFromStream(in);
@@ -293,6 +296,7 @@ public MultiMatchQueryBuilder field(String field, float boost) {
293296
if (Strings.isEmpty(field)) {
294297
throw new IllegalArgumentException("supplied field is null or empty.");
295298
}
299+
checkNegativeBoost(boost);
296300
this.fieldsBoosts.put(field, boost);
297301
return this;
298302
}
@@ -301,6 +305,9 @@ public MultiMatchQueryBuilder field(String field, float boost) {
301305
* Add several fields to run the query against with a specific boost.
302306
*/
303307
public MultiMatchQueryBuilder fields(Map<String, Float> fields) {
308+
for (float fieldBoost : fields.values()) {
309+
checkNegativeBoost(fieldBoost);
310+
}
304311
this.fieldsBoosts.putAll(fields);
305312
return this;
306313
}

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,10 @@ public QueryStringQueryBuilder(StreamInput in) throws IOException {
184184
defaultField = in.readOptionalString();
185185
int size = in.readVInt();
186186
for (int i = 0; i < size; i++) {
187-
fieldsAndWeights.put(in.readString(), in.readFloat());
187+
String field = in.readString();
188+
Float weight = in.readFloat();
189+
checkNegativeBoost(weight);
190+
fieldsAndWeights.put(field, weight);
188191
}
189192
defaultOperator = Operator.readFromStream(in);
190193
analyzer = in.readOptionalString();
@@ -339,6 +342,7 @@ public QueryStringQueryBuilder field(String field) {
339342
* Adds a field to run the query string against with a specific boost.
340343
*/
341344
public QueryStringQueryBuilder field(String field, float boost) {
345+
checkNegativeBoost(boost);
342346
this.fieldsAndWeights.put(field, boost);
343347
return this;
344348
}
@@ -347,6 +351,9 @@ public QueryStringQueryBuilder field(String field, float boost) {
347351
* Add several fields to run the query against with a specific boost.
348352
*/
349353
public QueryStringQueryBuilder fields(Map<String, Float> fields) {
354+
for (float fieldBoost : fields.values()) {
355+
checkNegativeBoost(fieldBoost);
356+
}
350357
this.fieldsAndWeights.putAll(fields);
351358
return this;
352359
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ public SimpleQueryStringBuilder(StreamInput in) throws IOException {
163163
for (int i = 0; i < size; i++) {
164164
String field = in.readString();
165165
Float weight = in.readFloat();
166+
checkNegativeBoost(weight);
166167
fields.put(field, weight);
167168
}
168169
fieldsAndWeights.putAll(fields);
@@ -258,13 +259,17 @@ public SimpleQueryStringBuilder field(String field, float boost) {
258259
if (Strings.isEmpty(field)) {
259260
throw new IllegalArgumentException("supplied field is null or empty");
260261
}
262+
checkNegativeBoost(boost);
261263
this.fieldsAndWeights.put(field, boost);
262264
return this;
263265
}
264266

265267
/** Add several fields to run the query against with a specific boost. */
266268
public SimpleQueryStringBuilder fields(Map<String, Float> fields) {
267269
Objects.requireNonNull(fields, "fields cannot be null");
270+
for (float fieldBoost : fields.values()) {
271+
checkNegativeBoost(fieldBoost);
272+
}
268273
this.fieldsAndWeights.putAll(fields);
269274
return this;
270275
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,10 @@ private List<Query> buildFieldQueries(MultiMatchQueryBuilder.Type type, Map<Stri
9696
// ignore unmapped fields
9797
continue;
9898
}
99-
Float boostValue = fieldNames.get(fieldName);
99+
float boostValue = fieldNames.getOrDefault(fieldName, 1.0f);
100100
Query query = parse(type.matchQueryType(), fieldName, value);
101101
query = Queries.maybeApplyMinimumShouldMatch(query, minimumShouldMatch);
102102
if (query != null
103-
&& boostValue != null
104103
&& boostValue != AbstractQueryBuilder.DEFAULT_BOOST
105104
&& query instanceof MatchNoDocsQuery == false) {
106105
query = new BoostQuery(query, boostValue);

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ public void testWithStopWords() throws Exception {
485485

486486
public void testDisMaxDeprecation() throws Exception {
487487
String json =
488-
"{\n" +
488+
"{\n" +
489489
" \"multi_match\" : {\n" +
490490
" \"query\" : \"foo:bar\",\n" +
491491
" \"use_dis_max\" : true\n" +
@@ -496,6 +496,15 @@ public void testDisMaxDeprecation() throws Exception {
496496
assertWarnings("Deprecated field [use_dis_max] used, replaced by [use tie_breaker instead]");
497497
}
498498

499+
public void testNegativeFieldBoost() throws IOException {
500+
Query query = new MultiMatchQueryBuilder("the quick fox")
501+
.field(STRING_FIELD_NAME, -1.0f)
502+
.field(STRING_FIELD_NAME_2)
503+
.toQuery(createShardContext());
504+
assertWarnings("setting a negative [boost] on a query is deprecated and will throw an error in the next major " +
505+
"version. You can use a value between 0 and 1 to deboost.");
506+
}
507+
499508
private static IndexMetaData newIndexMeta(String name, Settings oldIndexSettings, Settings indexSettings) {
500509
Settings build = Settings.builder().put(oldIndexSettings)
501510
.put(indexSettings)

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,15 @@ public void testAnalyzedPrefix() throws Exception {
14881488
assertEquals(expected, query);
14891489
}
14901490

1491+
public void testNegativeFieldBoost() throws IOException {
1492+
Query query = new QueryStringQueryBuilder("the quick fox")
1493+
.field(STRING_FIELD_NAME, -1.0f)
1494+
.field(STRING_FIELD_NAME_2)
1495+
.toQuery(createShardContext());
1496+
assertWarnings("setting a negative [boost] on a query is deprecated and will throw an error in the next major " +
1497+
"version. You can use a value between 0 and 1 to deboost.");
1498+
}
1499+
14911500
private static IndexMetaData newIndexMeta(String name, Settings oldIndexSettings, Settings indexSettings) {
14921501
Settings build = Settings.builder().put(oldIndexSettings)
14931502
.put(indexSettings)

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,15 @@ public void testUnmappedFieldNoTokenWithAndOperator() throws IOException {
739739
assertEquals(expected, query);
740740
}
741741

742+
public void testNegativeFieldBoost() throws IOException {
743+
Query query = new SimpleQueryStringBuilder("the quick fox")
744+
.field(STRING_FIELD_NAME, -1.0f)
745+
.field(STRING_FIELD_NAME_2)
746+
.toQuery(createShardContext());
747+
assertWarnings("setting a negative [boost] on a query is deprecated and will throw an error in the next major " +
748+
"version. You can use a value between 0 and 1 to deboost.");
749+
}
750+
742751
private static IndexMetaData newIndexMeta(String name, Settings oldIndexSettings, Settings indexSettings) {
743752
Settings build = Settings.builder().put(oldIndexSettings)
744753
.put(indexSettings)

test/framework/src/main/java/org/elasticsearch/test/AbstractQueryTestCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public void testNegativeBoosts() {
105105
QB testQuery = createTestQueryBuilder();
106106
testQuery.boost(-0.5f);
107107
assertWarnings("setting a negative [boost] on a query" +
108-
" is deprecated and will throw an error in the next version. You can use a value between 0 and 1 to deboost.");
108+
" is deprecated and will throw an error in the next major version. You can use a value between 0 and 1 to deboost.");
109109
}
110110

111111
/**

0 commit comments

Comments
 (0)