From 64b363838589641f15d8f9c86bfc261081bd0067 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 --- .../migration/migrate_7_0/mappings.asciidoc | 7 ++++++ .../index/mapper/CompletionFieldMapper.java | 20 +++++++++++++++++ .../mapper/CompletionFieldMapperTests.java | 22 +++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/docs/reference/migration/migrate_7_0/mappings.asciidoc b/docs/reference/migration/migrate_7_0/mappings.asciidoc index 653dd2fb4ca46..bfe80cf100c37 100644 --- a/docs/reference/migration/migrate_7_0/mappings.asciidoc +++ b/docs/reference/migration/migrate_7_0/mappings.asciidoc @@ -72,3 +72,10 @@ or `quadtree`. This will ensure compatibility with previously created indexes. The following type parameters are deprecated for the `geo_shape` field type: `tree`, `precision`, `tree_levels`, `distance_error_pct`, `points_only`, and `strategy`. They will be removed in a future version. + +[float] +==== Limiting the number of completion contexts + +The maximum allowed number of completion contexts in a mapping will be limited +to 10 in the next major version. Completion fields that define more than 10 +contexts in a mapping will log a deprecation warning in this version. \ No newline at end of file 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..df293f3afbfa7 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) { + 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..fb7f3cdc4e68e 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java @@ -54,6 +54,7 @@ import java.util.function.Function; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.elasticsearch.index.mapper.CompletionFieldMapper.COMPLETION_CONTEXTS_LIMIT; import static org.hamcrest.Matchers.arrayContainingInAnyOrder; import static org.hamcrest.Matchers.arrayWithSize; import static org.hamcrest.Matchers.containsString; @@ -908,6 +909,27 @@ 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 < 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); + + DocumentMapper mapper = createIndex(index).mapperService().documentMapperParser() + .parse("type1", new CompressedXContent(mappings)); + assertWarnings("You have defined more than [" + COMPLETION_CONTEXTS_LIMIT + "] completion contexts" + + " in the mapping for index [test]. The maximum allowed number of completion contexts in a mapping will be limited to " + + "[" + COMPLETION_CONTEXTS_LIMIT + "] starting in version [8.0]."); + } + private Matcher suggestField(String value) { return Matchers.allOf(hasProperty(IndexableField::stringValue, equalTo(value)), Matchers.instanceOf(SuggestField.class));