diff --git a/server/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java b/server/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java index 067061443d885..958ef8e9a386b 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java @@ -690,26 +690,26 @@ private static void parseCopyFields(DocumentParserContext context, List // find what the dynamic setting is given the current parse context and parent private static ObjectMapper.Dynamic dynamicOrDefault(ObjectMapper parentMapper, DocumentParserContext context) { ObjectMapper.Dynamic dynamic = parentMapper.dynamic(); + String parentName = parentMapper.name(); while (dynamic == null) { - int lastDotNdx = parentMapper.name().lastIndexOf('.'); + int lastDotNdx = parentName.lastIndexOf('.'); if (lastDotNdx == -1) { - // no dot means we the parent is the root, so just delegate to the default outside the loop - break; + // no dot means that the parent is the root + return context.root().dynamic() == null ? ObjectMapper.Dynamic.TRUE : context.root().dynamic(); } - String parentName = parentMapper.name().substring(0, lastDotNdx); - parentMapper = context.mappingLookup().objectMappers().get(parentName); - if (parentMapper == null) { + parentName = parentMapper.name().substring(0, lastDotNdx); + ObjectMapper parent = context.mappingLookup().objectMappers().get(parentName); + if (parent == null) { // If parentMapper is null, it means the parent of the current mapper is being dynamically created right now - parentMapper = context.getDynamicObjectMapper(parentName); - if (parentMapper == null) { + ObjectMapper.Builder dynamicObjectMapperBuilder = context.getDynamicObjectMapperBuilder(parentName); + if (dynamicObjectMapperBuilder == null) { // it can still happen that the path is ambiguous and we are not able to locate the parent break; } + dynamic = dynamicObjectMapperBuilder.dynamic; + } else { + dynamic = parent.dynamic(); } - dynamic = parentMapper.dynamic(); - } - if (dynamic == null) { - return context.root().dynamic() == null ? ObjectMapper.Dynamic.TRUE : context.root().dynamic(); } return dynamic; } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/DocumentParserContext.java b/server/src/main/java/org/elasticsearch/index/mapper/DocumentParserContext.java index 9b6353b862b24..3b1fad647d55c 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/DocumentParserContext.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/DocumentParserContext.java @@ -86,7 +86,7 @@ protected void addDoc(LuceneDocument doc) { private final Set ignoredFields; private final List dynamicMappers; private final Set newFieldsSeen; - private final Map dynamicObjectMappers; + private final Map dynamicObjectMappers; private final List dynamicRuntimeFields; private final DocumentDimensions dimensions; private String id; @@ -235,7 +235,7 @@ public final void addDynamicMapper(Mapper mapper) { mappingLookup.checkFieldLimit(indexSettings().getMappingTotalFieldsLimit(), newFieldsSeen.size()); } if (mapper instanceof ObjectMapper objectMapper) { - dynamicObjectMappers.put(objectMapper.name(), objectMapper); + dynamicObjectMappers.put(objectMapper.name(), objectMapper.newBuilder(this.indexSettings.getIndexVersionCreated())); // dynamic object mappers may have been obtained from applying a dynamic template, in which case their definition may contain // sub-fields as well as sub-objects that need to be added to the mappings for (Mapper submapper : objectMapper.mappers.values()) { @@ -265,13 +265,13 @@ public final List getDynamicMappers() { } /** - * Get a dynamic object mapper by name. Allows consumers to lookup objects that have been dynamically added as a result + * Get a dynamic object mapper builder by name. Allows consumers to lookup objects that have been dynamically added as a result * of parsing an incoming document. Used to find the parent object for new fields that are being dynamically mapped whose parent is * also not mapped yet. Such new fields will need to be dynamically added to their parent according to its dynamic behaviour. - * Holds a flat set of object mappers, meaning that an object field named foo.bar can be looked up directly with its + * Holds a flat set of object builders, meaning that an object field named foo.bar can be looked up directly with its * dotted name. */ - final ObjectMapper getDynamicObjectMapper(String name) { + final ObjectMapper.Builder getDynamicObjectMapperBuilder(String name) { return dynamicObjectMappers.get(name); } 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 3e629b4a21119..9a25351248561 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/ObjectMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/ObjectMapper.java @@ -136,11 +136,11 @@ private static ObjectMapper.Builder findObjectBuilder(String fullName, DocumentP return objectMapper.newBuilder(context.indexSettings().getIndexVersionCreated()); } // has the object mapper been added as a dynamic update already? - objectMapper = context.getDynamicObjectMapper(fullName); - if (objectMapper != null) { - return objectMapper.newBuilder(context.indexSettings().getIndexVersionCreated()); + Builder dynamicObjectMapperBuilder = context.getDynamicObjectMapperBuilder(fullName); + if (dynamicObjectMapperBuilder == null) { + throw new IllegalStateException("Missing intermediate object " + fullName); } - throw new IllegalStateException("Missing intermediate object " + fullName); + return dynamicObjectMapperBuilder; } protected final Map buildMappers(boolean root, MapperBuilderContext context) {