Skip to content

Commit 584fa26

Browse files
authored
Remove the ability to index or query context suggestions without context (elastic#31007)
This is a follow up of elastic#30712 that removes the ability to index or query and context enabled completion field without context. Relates elastic#30712
1 parent 5f5157a commit 584fa26

File tree

5 files changed

+33
-150
lines changed

5 files changed

+33
-150
lines changed

docs/reference/migration/migrate_7_0/search.asciidoc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ for a particular index with the index setting `index.max_regex_length`.
8585
Search requests with extra content after the main object will no longer be accepted
8686
by the `_search` endpoint. A parsing exception will be thrown instead.
8787

88+
==== Context Completion Suggester
89+
90+
The ability to query and index context enabled suggestions without context,
91+
deprecated in 6.x, has been removed. Context enabled suggestion queries
92+
without contexts have to visit every suggestion, which degrades the search performance
93+
considerably.
94+
8895
==== Semantics changed for `max_concurrent_shard_requests`
8996

9097
`max_concurrent_shard_requests` used to limit the total number of concurrent shard

rest-api-spec/src/main/resources/rest-api-spec/test/suggest/30_context.yml

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -337,11 +337,10 @@ setup:
337337
- match: { suggest.result.0.options.0.text: "foo" }
338338

339339
---
340-
"Indexing and Querying without contexts is deprecated":
340+
"Indexing and Querying without contexts is forbidden":
341341
- skip:
342342
version: " - 6.99.99"
343-
reason: this feature was deprecated in 7.0
344-
features: "warnings"
343+
reason: this feature was removed in 7.0
345344

346345
- do:
347346
index:
@@ -359,8 +358,7 @@ setup:
359358
color: "blue"
360359

361360
- do:
362-
warnings:
363-
- "The ability to index a suggestion with no context on a context enabled completion field is deprecated and will be removed in the next major release."
361+
catch: /Contexts are mandatory in context enabled completion field \[suggest_context\]/
364362
index:
365363
index: test
366364
type: test
@@ -373,22 +371,20 @@ setup:
373371
indices.refresh: {}
374372

375373
- do:
376-
warnings:
377-
- "The ability to query with no context on a context enabled completion field is deprecated and will be removed in the next major release."
374+
catch: /Missing mandatory contexts in context query/
378375
search:
376+
allow_partial_search_results: false
379377
body:
380378
suggest:
381379
result:
382380
text: "foo"
383381
completion:
384382
field: suggest_context
385383

386-
- length: { suggest.result: 1 }
387-
388384
- do:
389-
warnings:
390-
- "The ability to query with no context on a context enabled completion field is deprecated and will be removed in the next major release."
385+
catch: /Missing mandatory contexts in context query/
391386
search:
387+
allow_partial_search_results: false
392388
body:
393389
suggest:
394390
result:
@@ -397,12 +393,10 @@ setup:
397393
field: suggest_context
398394
contexts: {}
399395

400-
- length: { suggest.result: 1 }
401-
402396
- do:
403-
warnings:
404-
- "The ability to query with no context on a context enabled completion field is deprecated and will be removed in the next major release."
397+
catch: /Missing mandatory contexts in context query/
405398
search:
399+
allow_partial_search_results: false
406400
body:
407401
suggest:
408402
result:
@@ -411,5 +405,3 @@ setup:
411405
field: suggest_multi_contexts
412406
contexts:
413407
location: []
414-
415-
- length: { suggest.result: 1 }

rest-api-spec/src/main/resources/rest-api-spec/test/suggest/40_typed_keys.yml

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ setup:
1919
"type" : "category"
2020

2121
- do:
22-
warnings:
23-
- "The ability to index a suggestion with no context on a context enabled completion field is deprecated and will be removed in the next major release."
2422
bulk:
2523
refresh: true
2624
index: test
@@ -29,20 +27,12 @@ setup:
2927
- '{"index": {}}'
3028
- '{"title": "Elasticsearch in Action", "suggestions": {"input": "ELK in Action", "contexts": {"format": "ebook"}}}'
3129
- '{"index": {}}'
32-
- '{"title": "Elasticsearch - The Definitive Guide", "suggestions": {"input": ["Elasticsearch in Action"]}}'
30+
- '{"title": "Elasticsearch - The Definitive Guide", "suggestions": {"input": ["Elasticsearch in Action"], "contexts": {"format": "ebook"}}}'
3331

3432
---
3533
"Test typed keys parameter for suggesters":
36-
- skip:
37-
# version: " - 6.99.99"
38-
# reason: queying a context suggester with no context was deprecated in 7.0
39-
version: "all"
40-
reason: "Awaiting a fix: https://github.com/elastic/elasticsearch/issues/31698"
41-
features: "warnings"
4234

4335
- do:
44-
warnings:
45-
- "The ability to query with no context on a context enabled completion field is deprecated and will be removed in the next major release."
4636
search:
4737
typed_keys: true
4838
body:
@@ -53,10 +43,6 @@ setup:
5343
term_suggester:
5444
term:
5545
field: title
56-
completion_suggester:
57-
prefix: "Elastic"
58-
completion:
59-
field: suggestions
6046
context_suggester:
6147
prefix: "Elastic"
6248
completion:
@@ -68,6 +54,5 @@ setup:
6854
field: title
6955

7056
- is_true: suggest.term#term_suggester
71-
- is_true: suggest.completion#completion_suggester
7257
- is_true: suggest.completion#context_suggester
7358
- is_true: suggest.phrase#phrase_suggester

server/src/main/java/org/elasticsearch/search/suggest/completion/context/ContextMappings.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@
2525
import org.apache.lucene.util.CharsRefBuilder;
2626
import org.elasticsearch.ElasticsearchParseException;
2727
import org.elasticsearch.Version;
28-
import org.elasticsearch.common.logging.DeprecationLogger;
29-
import org.elasticsearch.common.logging.Loggers;
3028
import org.elasticsearch.common.xcontent.ToXContent;
3129
import org.elasticsearch.common.xcontent.XContentBuilder;
3230
import org.elasticsearch.index.mapper.CompletionFieldMapper;
@@ -54,9 +52,6 @@
5452
*/
5553
public class ContextMappings implements ToXContent {
5654

57-
private static final DeprecationLogger DEPRECATION_LOGGER =
58-
new DeprecationLogger(Loggers.getLogger(ContextMappings.class));
59-
6055
private final List<ContextMapping<?>> contextMappings;
6156
private final Map<String, ContextMapping<?>> contextNameMap;
6257

@@ -124,7 +119,7 @@ private class TypedContextField extends ContextSuggestField {
124119
private final ParseContext.Document document;
125120

126121
TypedContextField(String name, String value, int weight, Map<String, Set<CharSequence>> contexts,
127-
ParseContext.Document document) {
122+
ParseContext.Document document) {
128123
super(name, value, weight);
129124
this.contexts = contexts;
130125
this.document = document;
@@ -150,8 +145,7 @@ protected Iterable<CharSequence> contexts() {
150145
}
151146
}
152147
if (typedContexts.isEmpty()) {
153-
DEPRECATION_LOGGER.deprecated("The ability to index a suggestion with no context on a context enabled completion field" +
154-
" is deprecated and will be removed in the next major release.");
148+
throw new IllegalArgumentException("Contexts are mandatory in context enabled completion field [" + name + "]");
155149
}
156150
return typedContexts;
157151
}
@@ -186,8 +180,7 @@ public ContextQuery toContextQuery(CompletionQuery query, Map<String, List<Conte
186180
}
187181
}
188182
if (hasContext == false) {
189-
DEPRECATION_LOGGER.deprecated("The ability to query with no context on a context enabled completion field is deprecated " +
190-
"and will be removed in the next major release.");
183+
throw new IllegalArgumentException("Missing mandatory contexts in context query");
191184
}
192185
return typedContextQuery;
193186
}

server/src/test/java/org/elasticsearch/search/suggest/ContextCompletionSuggestSearchIT.java

Lines changed: 13 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@
1919
package org.elasticsearch.search.suggest;
2020

2121
import com.carrotsearch.randomizedtesting.generators.RandomStrings;
22-
2322
import org.apache.lucene.util.LuceneTestCase.SuppressCodecs;
2423
import org.elasticsearch.action.index.IndexRequestBuilder;
2524
import org.elasticsearch.action.index.IndexResponse;
2625
import org.elasticsearch.action.search.SearchResponse;
27-
import org.elasticsearch.common.geo.GeoHashUtils;
2826
import org.elasticsearch.common.geo.GeoPoint;
2927
import org.elasticsearch.common.settings.Settings;
3028
import org.elasticsearch.common.unit.Fuzziness;
@@ -95,7 +93,9 @@ public void testContextPrefix() throws Exception {
9593
.setSource(source));
9694
}
9795
indexRandom(true, indexRequestBuilders);
98-
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
96+
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg")
97+
.contexts(Collections.singletonMap("cat",
98+
Collections.singletonList(CategoryQueryContext.builder().setCategory("cat").setPrefix(true).build())));
9999
assertSuggestions("foo", prefix, "suggestion9", "suggestion8", "suggestion7", "suggestion6", "suggestion5");
100100
}
101101

@@ -126,7 +126,9 @@ public void testContextRegex() throws Exception {
126126
.setSource(source));
127127
}
128128
indexRandom(true, indexRequestBuilders);
129-
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).regex("sugg.*es");
129+
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).regex("sugg.*es")
130+
.contexts(Collections.singletonMap("cat",
131+
Collections.singletonList(CategoryQueryContext.builder().setCategory("cat").setPrefix(true).build())));
130132
assertSuggestions("foo", prefix, "sugg9estion", "sugg8estion", "sugg7estion", "sugg6estion", "sugg5estion");
131133
}
132134

@@ -157,7 +159,9 @@ public void testContextFuzzy() throws Exception {
157159
.setSource(source));
158160
}
159161
indexRandom(true, indexRequestBuilders);
160-
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg", Fuzziness.ONE);
162+
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg", Fuzziness.ONE)
163+
.contexts(Collections.singletonMap("cat",
164+
Collections.singletonList(CategoryQueryContext.builder().setCategory("cat").setPrefix(true).build())));
161165
assertSuggestions("foo", prefix, "sugxgestion9", "sugxgestion8", "sugxgestion7", "sugxgestion6", "sugxgestion5");
162166
}
163167

@@ -236,32 +240,6 @@ public void testSingleContextBoosting() throws Exception {
236240
assertSuggestions("foo", prefix, "suggestion8", "suggestion6", "suggestion4", "suggestion9", "suggestion2");
237241
}
238242

239-
public void testSingleContextMultipleContexts() throws Exception {
240-
CategoryContextMapping contextMapping = ContextBuilder.category("cat").field("cat").build();
241-
LinkedHashMap<String, ContextMapping<?>> map = new LinkedHashMap<>(Collections.singletonMap("cat", contextMapping));
242-
final CompletionMappingBuilder mapping = new CompletionMappingBuilder().context(map);
243-
createIndexAndMapping(mapping);
244-
int numDocs = 10;
245-
List<String> contexts = Arrays.asList("type1", "type2", "type3", "type4");
246-
List<IndexRequestBuilder> indexRequestBuilders = new ArrayList<>();
247-
for (int i = 0; i < numDocs; i++) {
248-
XContentBuilder source = jsonBuilder()
249-
.startObject()
250-
.startObject(FIELD)
251-
.field("input", "suggestion" + i)
252-
.field("weight", i + 1)
253-
.endObject()
254-
.field("cat", contexts)
255-
.endObject();
256-
indexRequestBuilders.add(client().prepareIndex(INDEX, TYPE, "" + i)
257-
.setSource(source));
258-
}
259-
indexRandom(true, indexRequestBuilders);
260-
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
261-
262-
assertSuggestions("foo", prefix, "suggestion9", "suggestion8", "suggestion7", "suggestion6", "suggestion5");
263-
}
264-
265243
public void testMultiContextFiltering() throws Exception {
266244
LinkedHashMap<String, ContextMapping<?>> map = new LinkedHashMap<>();
267245
map.put("cat", ContextBuilder.category("cat").field("cat").build());
@@ -295,14 +273,6 @@ public void testMultiContextFiltering() throws Exception {
295273
typeFilterSuggest.contexts(Collections.singletonMap("type", Arrays.asList(CategoryQueryContext.builder().setCategory("type2").build(),
296274
CategoryQueryContext.builder().setCategory("type1").build())));
297275
assertSuggestions("foo", typeFilterSuggest, "suggestion9", "suggestion6", "suggestion5", "suggestion2", "suggestion1");
298-
299-
CompletionSuggestionBuilder multiContextFilterSuggest = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
300-
// query context order should never matter
301-
Map<String, List<? extends ToXContent>> contextMap = new HashMap<>();
302-
contextMap.put("type", Collections.singletonList(CategoryQueryContext.builder().setCategory("type2").build()));
303-
contextMap.put("cat", Collections.singletonList(CategoryQueryContext.builder().setCategory("cat2").build()));
304-
multiContextFilterSuggest.contexts(contextMap);
305-
assertSuggestions("foo", multiContextFilterSuggest, "suggestion6", "suggestion2");
306276
}
307277

308278
@AwaitsFix(bugUrl = "multiple context boosting is broken, as a suggestion, contexts pair is treated as (num(context) entries)")
@@ -361,36 +331,6 @@ public void testMultiContextBoosting() throws Exception {
361331
assertSuggestions("foo", multiContextBoostSuggest, "suggestion9", "suggestion6", "suggestion5", "suggestion2", "suggestion1");
362332
}
363333

364-
public void testMissingContextValue() throws Exception {
365-
LinkedHashMap<String, ContextMapping<?>> map = new LinkedHashMap<>();
366-
map.put("cat", ContextBuilder.category("cat").field("cat").build());
367-
map.put("type", ContextBuilder.category("type").field("type").build());
368-
final CompletionMappingBuilder mapping = new CompletionMappingBuilder().context(map);
369-
createIndexAndMapping(mapping);
370-
int numDocs = 10;
371-
List<IndexRequestBuilder> indexRequestBuilders = new ArrayList<>();
372-
for (int i = 0; i < numDocs; i++) {
373-
XContentBuilder source = jsonBuilder()
374-
.startObject()
375-
.startObject(FIELD)
376-
.field("input", "suggestion" + i)
377-
.field("weight", i + 1)
378-
.endObject();
379-
if (randomBoolean()) {
380-
source.field("cat", "cat" + i % 2);
381-
}
382-
if (randomBoolean()) {
383-
source.field("type", "type" + i % 4);
384-
}
385-
source.endObject();
386-
indexRequestBuilders.add(client().prepareIndex(INDEX, TYPE, "" + i)
387-
.setSource(source));
388-
}
389-
indexRandom(true, indexRequestBuilders);
390-
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
391-
assertSuggestions("foo", prefix, "suggestion9", "suggestion8", "suggestion7", "suggestion6", "suggestion5");
392-
}
393-
394334
public void testSeveralContexts() throws Exception {
395335
LinkedHashMap<String, ContextMapping<?>> map = new LinkedHashMap<>();
396336
final int numContexts = randomIntBetween(2, 5);
@@ -417,35 +357,12 @@ public void testSeveralContexts() throws Exception {
417357
}
418358
indexRandom(true, indexRequestBuilders);
419359

420-
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
360+
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg")
361+
.contexts(Collections.singletonMap("type0",
362+
Collections.singletonList(CategoryQueryContext.builder().setCategory("type").setPrefix(true).build())));
421363
assertSuggestions("foo", prefix, "suggestion0", "suggestion1", "suggestion2", "suggestion3", "suggestion4");
422364
}
423365

424-
public void testSimpleGeoPrefix() throws Exception {
425-
LinkedHashMap<String, ContextMapping<?>> map = new LinkedHashMap<>();
426-
map.put("geo", ContextBuilder.geo("geo").build());
427-
final CompletionMappingBuilder mapping = new CompletionMappingBuilder().context(map);
428-
createIndexAndMapping(mapping);
429-
int numDocs = 10;
430-
List<IndexRequestBuilder> indexRequestBuilders = new ArrayList<>();
431-
for (int i = 0; i < numDocs; i++) {
432-
XContentBuilder source = jsonBuilder()
433-
.startObject()
434-
.startObject(FIELD)
435-
.field("input", "suggestion" + i)
436-
.field("weight", i + 1)
437-
.startObject("contexts")
438-
.field("geo", GeoHashUtils.stringEncode(1.2, 1.3))
439-
.endObject()
440-
.endObject().endObject();
441-
indexRequestBuilders.add(client().prepareIndex(INDEX, TYPE, "" + i)
442-
.setSource(source));
443-
}
444-
indexRandom(true, indexRequestBuilders);
445-
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
446-
assertSuggestions("foo", prefix, "suggestion9", "suggestion8", "suggestion7", "suggestion6", "suggestion5");
447-
}
448-
449366
public void testGeoFiltering() throws Exception {
450367
LinkedHashMap<String, ContextMapping<?>> map = new LinkedHashMap<>();
451368
map.put("geo", ContextBuilder.geo("geo").build());
@@ -468,8 +385,6 @@ public void testGeoFiltering() throws Exception {
468385
.setSource(source));
469386
}
470387
indexRandom(true, indexRequestBuilders);
471-
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
472-
assertSuggestions("foo", prefix, "suggestion9", "suggestion8", "suggestion7", "suggestion6", "suggestion5");
473388

474389
CompletionSuggestionBuilder geoFilteringPrefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg")
475390
.contexts(Collections.singletonMap("geo", Collections.singletonList(
@@ -500,8 +415,6 @@ public void testGeoBoosting() throws Exception {
500415
.setSource(source));
501416
}
502417
indexRandom(true, indexRequestBuilders);
503-
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
504-
assertSuggestions("foo", prefix, "suggestion9", "suggestion8", "suggestion7", "suggestion6", "suggestion5");
505418

506419
GeoQueryContext context1 = GeoQueryContext.builder().setGeoPoint(geoPoints[0]).setBoost(11).build();
507420
GeoQueryContext context2 = GeoQueryContext.builder().setGeoPoint(geoPoints[1]).build();
@@ -572,8 +485,6 @@ public void testGeoNeighbours() throws Exception {
572485
.setSource(source));
573486
}
574487
indexRandom(true, indexRequestBuilders);
575-
CompletionSuggestionBuilder prefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg");
576-
assertSuggestions("foo", prefix, "suggestion9", "suggestion8", "suggestion7", "suggestion6", "suggestion5");
577488

578489
CompletionSuggestionBuilder geoNeighbourPrefix = SuggestBuilders.completionSuggestion(FIELD).prefix("sugg")
579490
.contexts(Collections.singletonMap("geo", Collections.singletonList(GeoQueryContext.builder().setGeoPoint(GeoPoint.fromGeohash(geohash)).build())));
@@ -668,14 +579,9 @@ public void testSkipDuplicatesWithContexts() throws Exception {
668579
expected[i] = "suggestion" + (numUnique-1-i);
669580
}
670581
indexRandom(true, indexRequestBuilders);
671-
CompletionSuggestionBuilder completionSuggestionBuilder =
672-
SuggestBuilders.completionSuggestion(FIELD).prefix("sugg").skipDuplicates(true).size(numUnique);
673-
674-
assertSuggestions("suggestions", completionSuggestionBuilder, expected);
675-
676582
Map<String, List<? extends ToXContent>> contextMap = new HashMap<>();
677583
contextMap.put("cat", Arrays.asList(CategoryQueryContext.builder().setCategory("cat0").build()));
678-
completionSuggestionBuilder =
584+
CompletionSuggestionBuilder completionSuggestionBuilder =
679585
SuggestBuilders.completionSuggestion(FIELD).prefix("sugg").contexts(contextMap).skipDuplicates(true).size(numUnique);
680586

681587
String[] expectedModulo = Arrays.stream(expected)

0 commit comments

Comments
 (0)