From c1ab8218f117f18d4484667d98c4ba5b7b81880e Mon Sep 17 00:00:00 2001 From: Tamara Braun Date: Mon, 18 Feb 2019 12:51:40 +0100 Subject: [PATCH] Enforce Completion Context Limit (#38675) This change adds a limit to the number of completion contexts that a completion field can define. Closes #32741 --- docs/reference/migration/migrate_8_0.asciidoc | 16 ++++++++++++ .../migration/migrate_8_0/mappings.asciidoc | 8 +++++- .../suggesters/context-suggest.asciidoc | 2 ++ .../index/mapper/CompletionFieldMapper.java | 25 +++++++++++++++++++ .../mapper/CompletionFieldMapperTests.java | 22 ++++++++++++++++ 5 files changed, 72 insertions(+), 1 deletion(-) diff --git a/docs/reference/migration/migrate_8_0.asciidoc b/docs/reference/migration/migrate_8_0.asciidoc index ea1166e36d3b9..2ec007076d69b 100644 --- a/docs/reference/migration/migrate_8_0.asciidoc +++ b/docs/reference/migration/migrate_8_0.asciidoc @@ -13,4 +13,20 @@ coming[8.0.0] * <> +[float] +=== Indices created before 7.0 + +Elasticsearch 8.0 can read indices created in version 7.0 or above. An +Elasticsearch 8.0 node will not start in the presence of indices created in a +version of Elasticsearch before 7.0. + +[IMPORTANT] +.Reindex indices from Elasticsearch 6.x or before +========================================= + +Indices created in Elasticsearch 6.x or before will need to be reindexed with +Elasticsearch 7.x in order to be readable by Elasticsearch 8.x. + +========================================= + include::migrate_8_0/mappings.asciidoc[] \ No newline at end of file diff --git a/docs/reference/migration/migrate_8_0/mappings.asciidoc b/docs/reference/migration/migrate_8_0/mappings.asciidoc index ea36309447e4c..555162351b46a 100644 --- a/docs/reference/migration/migrate_8_0/mappings.asciidoc +++ b/docs/reference/migration/migrate_8_0/mappings.asciidoc @@ -7,4 +7,10 @@ The `nGram` and `edgeNGram` token filter names that have been deprecated since version 6.4 have been removed. Both token filters should be used by their -alternative names `ngram` and `edge_ngram` instead. \ No newline at end of file +alternative names `ngram` and `edge_ngram` instead. + +[float] +==== Limiting the number of completion contexts + +The number of completion contexts within a single completion field +has been limited to 10. \ No newline at end of file diff --git a/docs/reference/search/suggesters/context-suggest.asciidoc b/docs/reference/search/suggesters/context-suggest.asciidoc index 63692f0b06f82..77dd5745e159b 100644 --- a/docs/reference/search/suggesters/context-suggest.asciidoc +++ b/docs/reference/search/suggesters/context-suggest.asciidoc @@ -16,6 +16,8 @@ the field mapping. NOTE: It is mandatory to provide a context when indexing and querying a context enabled completion field. +NOTE: The maximum allowed number of completion field context mappings is 10. + The following defines types, each with two context mappings for a completion field: diff --git a/server/src/main/java/org/elasticsearch/index/mapper/CompletionFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/CompletionFieldMapper.java index df6a291372f64..5fd06633bcfc8 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/CompletionFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/CompletionFieldMapper.java @@ -18,6 +18,7 @@ */ package org.elasticsearch.index.mapper; +import org.apache.logging.log4j.LogManager; import org.apache.lucene.codecs.PostingsFormat; import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.Term; @@ -31,8 +32,10 @@ import org.apache.lucene.search.suggest.document.RegexCompletionQuery; import org.apache.lucene.search.suggest.document.SuggestField; import org.elasticsearch.Version; +import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParsingException; +import org.elasticsearch.common.logging.DeprecationLogger; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.common.util.set.Sets; @@ -85,6 +88,11 @@ public class CompletionFieldMapper extends FieldMapper implements ArrayValueMapperParser { public static final String CONTENT_TYPE = "completion"; + /** + * Maximum allowed number of completion contexts in a mapping. + */ + static final int COMPLETION_CONTEXTS_LIMIT = 10; + public static class Defaults { public static final MappedFieldType FIELD_TYPE = new CompletionFieldType(); static { @@ -354,6 +362,8 @@ public static class Builder extends FieldMapper.Builder COMPLETION_CONTEXTS_LIMIT) { + if (context.indexCreatedVersion().onOrAfter(Version.V_8_0_0)) { + throw new IllegalArgumentException( + "Limit of completion field contexts [" + COMPLETION_CONTEXTS_LIMIT + "] has been exceeded"); + } else { + deprecationLogger.deprecated("You have defined more than [" + COMPLETION_CONTEXTS_LIMIT + "] completion contexts" + + " in the mapping for index [" + context.indexSettings().get(IndexMetaData.SETTING_INDEX_PROVIDED_NAME) + "]. " + + "The maximum allowed number of completion contexts in a mapping will be limited to " + + "[" + COMPLETION_CONTEXTS_LIMIT + "] starting in version [8.0]."); + } + } + } } private int maxInputLength; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java index 7354af17043eb..7d16c01e9daaf 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java @@ -908,6 +908,28 @@ public void testEmptyName() throws IOException { assertThat(e.getMessage(), containsString("name cannot be empty string")); } + public void testLimitOfContextMappings() throws Throwable { + final String index = "test"; + XContentBuilder mappingBuilder = XContentFactory.jsonBuilder().startObject().startObject("properties") + .startObject("suggest").field("type", "completion").startArray("contexts"); + for (int i = 0; i < CompletionFieldMapper.COMPLETION_CONTEXTS_LIMIT + 1; i++) { + mappingBuilder.startObject(); + mappingBuilder.field("name", Integer.toString(i)); + mappingBuilder.field("type", "category"); + mappingBuilder.endObject(); + } + + mappingBuilder.endArray().endObject().endObject().endObject(); + String mappings = Strings.toString(mappingBuilder); + + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> { + createIndex(index).mapperService().documentMapperParser().parse("type1", new CompressedXContent(mappings)); + }); + assertTrue(e.getMessage(), + e.getMessage().contains("Limit of completion field contexts [" + + CompletionFieldMapper.COMPLETION_CONTEXTS_LIMIT + "] has been exceeded")); + } + private Matcher suggestField(String value) { return Matchers.allOf(hasProperty(IndexableField::stringValue, equalTo(value)), Matchers.instanceOf(SuggestField.class));