diff --git a/server/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java b/server/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java index 9745ba80ddc6a..8e0f5de3d9e64 100644 --- a/server/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java +++ b/server/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java @@ -144,6 +144,7 @@ public final class IndexScopedSettings extends AbstractScopedSettings { MapperService.INDEX_MAPPING_NESTED_DOCS_LIMIT_SETTING, MapperService.INDEX_MAPPING_TOTAL_FIELDS_LIMIT_SETTING, MapperService.INDEX_MAPPING_DEPTH_LIMIT_SETTING, + MapperService.INDEX_MAPPING_DIMENSION_FIELDS_LIMIT_SETTING, MapperService.INDEX_MAPPING_FIELD_NAME_LENGTH_LIMIT_SETTING, BitsetFilterCache.INDEX_LOAD_RANDOM_ACCESS_FILTERS_EAGERLY_SETTING, IndexModule.INDEX_STORE_TYPE_SETTING, diff --git a/server/src/main/java/org/elasticsearch/index/IndexSettings.java b/server/src/main/java/org/elasticsearch/index/IndexSettings.java index f866bb60f883a..c36db7e5a385d 100644 --- a/server/src/main/java/org/elasticsearch/index/IndexSettings.java +++ b/server/src/main/java/org/elasticsearch/index/IndexSettings.java @@ -31,6 +31,7 @@ import java.util.function.Function; import static org.elasticsearch.index.mapper.MapperService.INDEX_MAPPING_DEPTH_LIMIT_SETTING; +import static org.elasticsearch.index.mapper.MapperService.INDEX_MAPPING_DIMENSION_FIELDS_LIMIT_SETTING; import static org.elasticsearch.index.mapper.MapperService.INDEX_MAPPING_FIELD_NAME_LENGTH_LIMIT_SETTING; import static org.elasticsearch.index.mapper.MapperService.INDEX_MAPPING_NESTED_DOCS_LIMIT_SETTING; import static org.elasticsearch.index.mapper.MapperService.INDEX_MAPPING_NESTED_FIELDS_LIMIT_SETTING; @@ -379,6 +380,7 @@ private void setRetentionLeaseMillis(final TimeValue retentionLease) { private volatile long mappingTotalFieldsLimit; private volatile long mappingDepthLimit; private volatile long mappingFieldNameLengthLimit; + private volatile long mappingDimensionFieldsLimit; /** * The maximum number of refresh listeners allows on this shard. @@ -503,6 +505,7 @@ public IndexSettings(final IndexMetadata indexMetadata, final Settings nodeSetti mappingTotalFieldsLimit = scopedSettings.get(INDEX_MAPPING_TOTAL_FIELDS_LIMIT_SETTING); mappingDepthLimit = scopedSettings.get(INDEX_MAPPING_DEPTH_LIMIT_SETTING); mappingFieldNameLengthLimit = scopedSettings.get(INDEX_MAPPING_FIELD_NAME_LENGTH_LIMIT_SETTING); + mappingDimensionFieldsLimit = scopedSettings.get(INDEX_MAPPING_DIMENSION_FIELDS_LIMIT_SETTING); scopedSettings.addSettingsUpdateConsumer(MergePolicyConfig.INDEX_COMPOUND_FORMAT_SETTING, mergePolicyConfig::setNoCFSRatio); scopedSettings.addSettingsUpdateConsumer(MergePolicyConfig.INDEX_MERGE_POLICY_DELETES_PCT_ALLOWED_SETTING, @@ -558,6 +561,7 @@ public IndexSettings(final IndexMetadata indexMetadata, final Settings nodeSetti scopedSettings.addSettingsUpdateConsumer(INDEX_MAPPING_TOTAL_FIELDS_LIMIT_SETTING, this::setMappingTotalFieldsLimit); scopedSettings.addSettingsUpdateConsumer(INDEX_MAPPING_DEPTH_LIMIT_SETTING, this::setMappingDepthLimit); scopedSettings.addSettingsUpdateConsumer(INDEX_MAPPING_FIELD_NAME_LENGTH_LIMIT_SETTING, this::setMappingFieldNameLengthLimit); + scopedSettings.addSettingsUpdateConsumer(INDEX_MAPPING_DIMENSION_FIELDS_LIMIT_SETTING, this::setMappingDimensionFieldsLimit); } private void setSearchIdleAfter(TimeValue searchIdleAfter) { this.searchIdleAfter = searchIdleAfter; } @@ -1021,4 +1025,12 @@ public long getMappingFieldNameLengthLimit() { private void setMappingFieldNameLengthLimit(long value) { this.mappingFieldNameLengthLimit = value; } + + public long getMappingDimensionFieldsLimit() { + return mappingDimensionFieldsLimit; + } + + private void setMappingDimensionFieldsLimit(long value) { + this.mappingDimensionFieldsLimit = value; + } } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/IpFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/IpFieldMapper.java index 1305d95053c8b..608041a4dcd35 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/IpFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/IpFieldMapper.java @@ -8,6 +8,7 @@ package org.elasticsearch.index.mapper; +import org.apache.lucene.document.Field; import org.apache.lucene.document.InetAddressPoint; import org.apache.lucene.document.SortedSetDocValuesField; import org.apache.lucene.document.StoredField; @@ -72,8 +73,7 @@ public static class Builder extends FieldMapper.Builder { private final Parameter onScriptError = Parameter.onScriptErrorParam(m -> toType(m).onScriptError, script); private final Parameter> meta = Parameter.metaParam(); - private final Parameter dimension - = Parameter.boolParam("dimension", false, m -> toType(m).dimension, false); + private final Parameter dimension; private final boolean ignoreMalformedByDefault; private final Version indexCreatedVersion; @@ -88,6 +88,14 @@ public Builder(String name, ScriptCompiler scriptCompiler, boolean ignoreMalform = Parameter.boolParam("ignore_malformed", true, m -> toType(m).ignoreMalformed, ignoreMalformedByDefault); this.script.precludesParameters(nullValue, ignoreMalformed); addScriptValidation(script, indexed, hasDocValues); + this.dimension = Parameter.boolParam("dimension", false, m -> toType(m).dimension, false) + .setValidator(v -> { + if (v && (indexed.getValue() == false || hasDocValues.getValue() == false)) { + throw new IllegalArgumentException( + "Field [dimension] requires that [" + indexed.name + "] and [" + hasDocValues.name + "] are true" + ); + } + }); } Builder nullValue(String nullValue) { @@ -467,7 +475,17 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio private void indexValue(DocumentParserContext context, InetAddress address) { if (indexed) { - context.doc().add(new InetAddressPoint(fieldType().name(), address)); + Field field = new InetAddressPoint(fieldType().name(), address); + if (dimension) { + // Add dimension field with key so that we ensure it is single-valued. + // Dimension fields are always indexed. + if (context.doc().getByKey(fieldType().name()) != null) { + throw new IllegalArgumentException("Dimension field [" + fieldType().name() + "] cannot be a multi-valued field."); + } + context.doc().addWithKey(fieldType().name(), field); + } else { + context.doc().add(field); + } } if (hasDocValues) { context.doc().add(new SortedSetDocValuesField(fieldType().name(), new BytesRef(InetAddressPoint.encode(address)))); diff --git a/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java index d5e1a00dc72c2..1a3db9d4f96d5 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java @@ -124,12 +124,13 @@ public Builder(String name, IndexAnalyzers indexAnalyzers, ScriptCompiler script this.script.precludesParameters(nullValue); addScriptValidation(script, indexed, hasDocValues); - this.dimension = Parameter.boolParam("dimension", false, m -> toType(m).dimension, false) - .setValidator(v -> { - if (v && ignoreAbove.getValue() < ignoreAbove.getDefaultValue()) { - throw new IllegalArgumentException("Field [ignore_above] cannot be set in conjunction with field [dimension]"); - } - }); + this.dimension = Parameter.boolParam("dimension", false, m -> toType(m).dimension, false).setValidator(v -> { + if (v && (indexed.getValue() == false || hasDocValues.getValue() == false)) { + throw new IllegalArgumentException( + "Field [dimension] requires that [" + indexed.name + "] and [" + hasDocValues.name + "] are true" + ); + } + }).precludesParameters(normalizer, ignoreAbove); } public Builder(String name) { @@ -431,6 +432,9 @@ public boolean isDimension() { } } + /** The maximum keyword length allowed for a dimension field */ + private static final int DIMENSION_MAX_BYTES = 1024; + private final boolean indexed; private final boolean hasDocValues; private final String nullValue; @@ -509,9 +513,24 @@ private void indexValue(DocumentParserContext context, String value) { // convert to utf8 only once before feeding postings/dv/stored fields final BytesRef binaryValue = new BytesRef(value); + if (dimension && binaryValue.length > DIMENSION_MAX_BYTES) { + throw new IllegalArgumentException( + "Dimension field [" + fieldType().name() + "] cannot be more than [" + DIMENSION_MAX_BYTES + "] bytes long." + ); + } if (fieldType.indexOptions() != IndexOptions.NONE || fieldType.stored()) { Field field = new KeywordField(fieldType().name(), binaryValue, fieldType); - context.doc().add(field); + if (dimension) { + // Check that a dimension field is single-valued and not an array + if (context.doc().getByKey(fieldType().name()) != null) { + throw new IllegalArgumentException("Dimension field [" + fieldType().name() + "] cannot be a multi-valued field."); + } + // Add dimension field with key so that we ensure it is single-valued. + // Dimension fields are always indexed. + context.doc().addWithKey(fieldType().name(), field); + } else { + context.doc().add(field); + } if (fieldType().hasDocValues() == false && fieldType.omitNorms()) { context.addToFieldNames(fieldType().name()); diff --git a/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java b/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java index 8aed9fdbdb049..0d5edfa025980 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java @@ -165,6 +165,13 @@ public boolean isAggregatable() { } } + /** + * @return true if field has been marked as a dimension field + */ + public boolean isDimension() { + return false; + } + /** Generates a query that will only match documents that contain the given value. * The default implementation returns a {@link TermQuery} over the value bytes * @throws IllegalArgumentException if {@code value} cannot be converted to the expected data type or if the field is not searchable diff --git a/server/src/main/java/org/elasticsearch/index/mapper/MapperService.java b/server/src/main/java/org/elasticsearch/index/mapper/MapperService.java index dba9be14862fe..d18588c09a38e 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/MapperService.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/MapperService.java @@ -89,6 +89,9 @@ public enum MergeReason { Setting.longSetting("index.mapping.depth.limit", 20L, 1, Property.Dynamic, Property.IndexScope); public static final Setting INDEX_MAPPING_FIELD_NAME_LENGTH_LIMIT_SETTING = Setting.longSetting("index.mapping.field_name_length.limit", Long.MAX_VALUE, 1L, Property.Dynamic, Property.IndexScope); + public static final Setting INDEX_MAPPING_DIMENSION_FIELDS_LIMIT_SETTING = + Setting.longSetting("index.mapping.dimension_fields.limit", 16, 0, Property.Dynamic, Property.IndexScope); + private final IndexAnalyzers indexAnalyzers; private final MappingParser mappingParser; diff --git a/server/src/main/java/org/elasticsearch/index/mapper/MappingLookup.java b/server/src/main/java/org/elasticsearch/index/mapper/MappingLookup.java index 975a3860e42f8..2b0e3ba19be83 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/MappingLookup.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/MappingLookup.java @@ -204,6 +204,7 @@ void checkLimits(IndexSettings settings) { checkObjectDepthLimit(settings.getMappingDepthLimit()); checkFieldNameLengthLimit(settings.getMappingFieldNameLengthLimit()); checkNestedLimit(settings.getMappingNestedFieldsLimit()); + checkDimensionFieldLimit(settings.getMappingDimensionFieldsLimit()); } private void checkFieldLimit(long limit) { @@ -217,6 +218,16 @@ void checkFieldLimit(long limit, int additionalFieldsToAdd) { } } + private void checkDimensionFieldLimit(long limit) { + long dimensionFieldCount = fieldMappers.values() + .stream() + .filter(m -> m instanceof FieldMapper && ((FieldMapper) m).fieldType().isDimension()) + .count(); + if (dimensionFieldCount > limit) { + throw new IllegalArgumentException("Limit of total dimension fields [" + limit + "] has been exceeded"); + } + } + private void checkObjectDepthLimit(long limit) { for (String objectPath : objectMappers.keySet()) { int numDots = 0; diff --git a/server/src/main/java/org/elasticsearch/index/mapper/NumberFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/NumberFieldMapper.java index 02ad73cad435a..e66f829c9cfc9 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/NumberFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/NumberFieldMapper.java @@ -119,6 +119,11 @@ public Builder(String name, NumberType type, ScriptCompiler compiler, boolean ig if (v && EnumSet.of(NumberType.INTEGER, NumberType.LONG, NumberType.BYTE, NumberType.SHORT).contains(type) == false) { throw new IllegalArgumentException("Parameter [dimension] cannot be set to numeric type [" + type.name + "]"); } + if (v && (indexed.getValue() == false || hasDocValues.getValue() == false)) { + throw new IllegalArgumentException( + "Field [dimension] requires that [" + indexed.name + "] and [" + hasDocValues.name + "] are true" + ); + } }); this.script.precludesParameters(ignoreMalformed, coerce, nullValue); @@ -1174,8 +1179,20 @@ private static Number value(XContentParser parser, NumberType numberType, Number } private void indexValue(DocumentParserContext context, Number numericValue) { - context.doc().addAll(fieldType().type.createFields(fieldType().name(), numericValue, - indexed, hasDocValues, stored)); + List fields = fieldType().type.createFields(fieldType().name(), numericValue, indexed, hasDocValues, stored); + if (dimension) { + // Check that a dimension field is single-valued and not an array + if (context.doc().getByKey(fieldType().name()) != null) { + throw new IllegalArgumentException("Dimension field [" + fieldType().name() + "] cannot be a multi-valued field."); + } + if (fields.size() > 0) { + // Add the first field by key so that we can validate if it has been added + context.doc().addWithKey(fieldType().name(), fields.get(0)); + context.doc().addAll(fields.subList(1, fields.size())); + } + } else { + context.doc().addAll(fields); + } if (hasDocValues == false && (stored || indexed)) { context.addToFieldNames(fieldType().name()); diff --git a/server/src/test/java/org/elasticsearch/index/mapper/DocumentMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/DocumentMapperTests.java index 97d20baa6843e..ffa1374a08449 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/DocumentMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/DocumentMapperTests.java @@ -287,4 +287,17 @@ public void testEmptyDocumentMapper() { assertEquals(10, documentMapper.mappers().getMapping().getMetadataMappersMap().size()); assertEquals(10, documentMapper.mappers().getMatchingFieldNames("*").size()); } + + public void testTooManyDimensionFields() { + // By default no more than 16 dimensions per document are supported + IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> createDocumentMapper(mapping(b -> { + for (int i = 0; i < 17; i++) { + b.startObject("field" + i) + .field("type", randomFrom("ip", "keyword", "long", "integer", "byte", "short")) + .field("dimension", true) + .endObject(); + } + }))); + assertThat(e.getMessage(), containsString("Limit of total dimension fields [16] has been exceeded")); + } } diff --git a/server/src/test/java/org/elasticsearch/index/mapper/IpFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/IpFieldMapperTests.java index 76cb8a915bff8..3373d08d67fc2 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/IpFieldMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/IpFieldMapperTests.java @@ -215,6 +215,45 @@ public void testDimension() throws IOException { assertDimension(false, IpFieldMapper.IpFieldType::isDimension); } + public void testDimensionIndexedAndDocvalues() { + { + Exception e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true).field("index", false).field("doc_values", false); + }))); + assertThat(e.getCause().getMessage(), + containsString("Field [dimension] requires that [index] and [doc_values] are true")); + } + { + Exception e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true).field("index", true).field("doc_values", false); + }))); + assertThat(e.getCause().getMessage(), + containsString("Field [dimension] requires that [index] and [doc_values] are true")); + } + { + Exception e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true).field("index", false).field("doc_values", true); + }))); + assertThat(e.getCause().getMessage(), + containsString("Field [dimension] requires that [index] and [doc_values] are true")); + } + } + + public void testDimensionMultiValuedField() throws IOException { + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true); + })); + + Exception e = expectThrows(MapperParsingException.class, + () -> mapper.parse(source(b -> b.array("field", "192.168.1.1", "192.168.1.1")))); + assertThat(e.getCause().getMessage(), + containsString("Dimension field [field] cannot be a multi-valued field")); + } + @Override protected String generateRandomInputValue(MappedFieldType ft) { return NetworkAddress.format(randomIp(randomBoolean())); diff --git a/server/src/test/java/org/elasticsearch/index/mapper/KeywordFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/KeywordFieldMapperTests.java index 92dcca91e47d9..4d53b9435934b 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/KeywordFieldMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/KeywordFieldMapperTests.java @@ -320,6 +320,66 @@ public void testDimensionAndIgnoreAbove() { containsString("Field [ignore_above] cannot be set in conjunction with field [dimension]")); } + public void testDimensionAndNormalizer() { + Exception e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true).field("normalizer", "my_normalizer"); + }))); + assertThat(e.getCause().getMessage(), + containsString("Field [normalizer] cannot be set in conjunction with field [dimension]")); + } + + public void testDimensionIndexedAndDocvalues() { + { + Exception e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true).field("index", false).field("doc_values", false); + }))); + assertThat(e.getCause().getMessage(), + containsString("Field [dimension] requires that [index] and [doc_values] are true")); + } + { + Exception e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true).field("index", true).field("doc_values", false); + }))); + assertThat(e.getCause().getMessage(), + containsString("Field [dimension] requires that [index] and [doc_values] are true")); + } + { + Exception e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true).field("index", false).field("doc_values", true); + }))); + assertThat(e.getCause().getMessage(), + containsString("Field [dimension] requires that [index] and [doc_values] are true")); + } + } + + public void testDimensionMultiValuedField() throws IOException { + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true); + })); + + Exception e = expectThrows(MapperParsingException.class, + () -> mapper.parse(source(b -> b.array("field", "1234", "45678")))); + assertThat(e.getCause().getMessage(), + containsString("Dimension field [field] cannot be a multi-valued field")); + } + + public void testDimensionExtraLongKeyword() throws IOException { + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true); + })); + + Exception e = expectThrows(MapperParsingException.class, + () -> mapper.parse(source(b -> b.field("field", randomAlphaOfLengthBetween(1024, 2048))))); + assertThat(e.getCause().getMessage(), + containsString("Dimension field [field] cannot be more than [1024] bytes long.")); + } + public void testConfigureSimilarity() throws IOException { MapperService mapperService = createMapperService( fieldMapping(b -> b.field("type", "keyword").field("similarity", "boolean")) diff --git a/server/src/test/java/org/elasticsearch/index/mapper/WholeNumberFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/WholeNumberFieldMapperTests.java index da8b37a662fdc..ea41733e59184 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/WholeNumberFieldMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/WholeNumberFieldMapperTests.java @@ -12,6 +12,8 @@ import java.io.IOException; +import static org.hamcrest.Matchers.containsString; + public abstract class WholeNumberFieldMapperTests extends NumberFieldMapperTests { protected void testDecimalCoerce() throws IOException { @@ -33,6 +35,45 @@ public void testDimension() throws IOException { assertDimension(false, NumberFieldMapper.NumberFieldType::isDimension); } + public void testDimensionIndexedAndDocvalues() { + { + Exception e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true).field("index", false).field("doc_values", false); + }))); + assertThat(e.getCause().getMessage(), + containsString("Field [dimension] requires that [index] and [doc_values] are true")); + } + { + Exception e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true).field("index", true).field("doc_values", false); + }))); + assertThat(e.getCause().getMessage(), + containsString("Field [dimension] requires that [index] and [doc_values] are true")); + } + { + Exception e = expectThrows(MapperParsingException.class, () -> createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true).field("index", false).field("doc_values", true); + }))); + assertThat(e.getCause().getMessage(), + containsString("Field [dimension] requires that [index] and [doc_values] are true")); + } + } + + public void testDimensionMultiValuedField() throws IOException { + DocumentMapper mapper = createDocumentMapper(fieldMapping(b -> { + minimalMapping(b); + b.field("dimension", true); + })); + + Exception e = expectThrows(MapperParsingException.class, + () -> mapper.parse(source(b -> b.array("field", randomNumber(), randomNumber(), randomNumber())))); + assertThat(e.getCause().getMessage(), + containsString("Dimension field [field] cannot be a multi-valued field")); + } + @Override protected void registerParameters(ParameterChecker checker) throws IOException { super.registerParameters(checker); diff --git a/x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/action/TransportResumeFollowActionTests.java b/x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/action/TransportResumeFollowActionTests.java index c76fa1277f8b4..561015a5888be 100644 --- a/x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/action/TransportResumeFollowActionTests.java +++ b/x-pack/plugin/ccr/src/test/java/org/elasticsearch/xpack/ccr/action/TransportResumeFollowActionTests.java @@ -216,6 +216,7 @@ public void testDynamicIndexSettingsAreClassified() { replicatedSettings.add(MapperService.INDEX_MAPPING_NESTED_FIELDS_LIMIT_SETTING); replicatedSettings.add(MapperService.INDEX_MAPPING_DEPTH_LIMIT_SETTING); replicatedSettings.add(MapperService.INDEX_MAPPING_FIELD_NAME_LENGTH_LIMIT_SETTING); + replicatedSettings.add(MapperService.INDEX_MAPPING_DIMENSION_FIELDS_LIMIT_SETTING); replicatedSettings.add(IndexSettings.MAX_NGRAM_DIFF_SETTING); replicatedSettings.add(IndexSettings.MAX_SHINGLE_DIFF_SETTING);