diff --git a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java index dd7335e1831..75c06a588a8 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java @@ -859,7 +859,8 @@ final class DocumentParser { Mapper.BuilderContext builderContext = new Mapper.BuilderContext(context.indexSettings(), context.path()); mapper = (ObjectMapper) builder.build(builderContext); if (mapper.nested() != ObjectMapper.Nested.NO) { - throw new MapperParsingException("It is forbidden to create dynamic nested objects ([" + context.path().pathAsText(paths[i]) + "]) through `copy_to`"); + throw new MapperParsingException("It is forbidden to create dynamic nested objects ([" + context.path().pathAsText(paths[i]) + + "]) through `copy_to` or dots in field names"); } context.addDynamicMapper(mapper); break; @@ -909,6 +910,11 @@ final class DocumentParser { return null; } objectMapper = (ObjectMapper)mapper; + if (objectMapper.nested().isNested()) { + throw new MapperParsingException("Cannot add a value for field [" + + fieldName + "] since one of the intermediate objects is mapped as a nested object: [" + + mapper.name() + "]"); + } } return objectMapper.getMapper(subfields[subfields.length - 1]); } diff --git a/core/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java b/core/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java index 55f6b0b52cd..f5a92d3f979 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/DocumentParserTests.java @@ -120,6 +120,51 @@ public class DocumentParserTests extends ESSingleNodeTestCase { assertEquals("789", values[2]); } + public void testDotsWithExistingNestedMapper() throws Exception { + DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") + .startObject("foo").field("type", "nested").startObject("properties") + .startObject("bar").field("type", "integer") + .endObject().endObject().endObject().endObject().endObject().endObject().string(); + DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + + BytesReference bytes = XContentFactory.jsonBuilder() + .startObject() + .field("foo.bar", 123) + .endObject().bytes(); + MapperParsingException e = expectThrows(MapperParsingException.class, + () -> mapper.parse("test", "type", "1", bytes)); + assertEquals( + "Cannot add a value for field [foo.bar] since one of the intermediate objects is mapped as a nested object: [foo]", + e.getMessage()); + } + + public void testDotsWithDynamicNestedMapper() throws Exception { + DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startArray("dynamic_templates") + .startObject() + .startObject("objects_as_nested") + .field("match_mapping_type", "object") + .startObject("mapping") + .field("type", "nested") + .endObject() + .endObject() + .endObject() + .endArray().endObject().endObject().string(); + DocumentMapper mapper = mapperParser.parse("type", new CompressedXContent(mapping)); + + BytesReference bytes = XContentFactory.jsonBuilder() + .startObject() + .field("foo.bar",42) + .endObject().bytes(); + MapperParsingException e = expectThrows(MapperParsingException.class, + () -> mapper.parse("test", "type", "1", bytes)); + assertEquals( + "It is forbidden to create dynamic nested objects ([foo]) through `copy_to` or dots in field names", + e.getMessage()); + } + public void testPropagateDynamicWithExistingMapper() throws Exception { DocumentMapperParser mapperParser = createIndex("test").mapperService().documentMapperParser(); String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")