diff --git a/server/src/main/java/org/elasticsearch/index/mapper/ObjectMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/ObjectMapper.java index b1ec7d0361cb4..33ef59bba800f 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/ObjectMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/ObjectMapper.java @@ -465,9 +465,7 @@ protected void doMerge(final ObjectMapper mergeWith) { this.dynamic = mergeWith.dynamic; } - if (isEnabled() != mergeWith.isEnabled()) { - throw new MapperException("The [enabled] parameter can't be updated for the object mapping [" + name() + "]."); - } + checkObjectMapperParameters(mergeWith); for (Mapper mergeWithMapper : mergeWith) { Mapper mergeIntoMapper = mappers.get(mergeWithMapper.simpleName()); @@ -484,6 +482,22 @@ protected void doMerge(final ObjectMapper mergeWith) { } } + private void checkObjectMapperParameters(final ObjectMapper mergeWith) { + if (isEnabled() != mergeWith.isEnabled()) { + throw new MapperException("The [enabled] parameter can't be updated for the object mapping [" + name() + "]."); + } + + if (nested().isIncludeInParent() != mergeWith.nested().isIncludeInParent()) { + throw new MapperException("The [include_in_parent] parameter can't be updated for the nested object mapping [" + + name() + "]."); + } + + if (nested().isIncludeInRoot() != mergeWith.nested().isIncludeInRoot()) { + throw new MapperException("The [include_in_root] parameter can't be updated for the nested object mapping [" + + name() + "]."); + } + } + @Override public ObjectMapper updateFieldType(Map fullNameToFieldType) { List updatedMappers = null; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/NestedObjectMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/NestedObjectMapperTests.java index b243e0f655ada..661306aea4f50 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/NestedObjectMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/NestedObjectMapperTests.java @@ -742,4 +742,31 @@ public void testReorderParent() throws IOException { assertThat(doc.docs().get(1).get("nested1.field2"), equalTo("4")); assertThat(doc.docs().get(2).get("field"), equalTo("value")); } + + public void testMergeNestedMappings() throws IOException { + MapperService mapperService = createIndex("index1", Settings.EMPTY, jsonBuilder().startObject() + .startObject("properties") + .startObject("nested1") + .field("type", "nested") + .endObject() + .endObject().endObject()).mapperService(); + + String mapping1 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") + .startObject("nested1").field("type", "nested").field("include_in_parent", true) + .endObject().endObject().endObject().endObject()); + + // cannot update `include_in_parent` dynamically + MapperException e1 = expectThrows(MapperException.class, () -> mapperService.merge("type", + new CompressedXContent(mapping1), MergeReason.MAPPING_UPDATE)); + assertEquals("The [include_in_parent] parameter can't be updated for the nested object mapping [nested1].", e1.getMessage()); + + String mapping2 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") + .startObject("nested1").field("type", "nested").field("include_in_root", true) + .endObject().endObject().endObject().endObject()); + + // cannot update `include_in_root` dynamically + MapperException e2 = expectThrows(MapperException.class, () -> mapperService.merge("type", + new CompressedXContent(mapping2), MergeReason.MAPPING_UPDATE)); + assertEquals("The [include_in_root] parameter can't be updated for the nested object mapping [nested1].", e2.getMessage()); + } }