From 2fe7cde8d1b44215657a6d7096e4f03dc0eda3db Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Sun, 31 May 2015 13:20:49 +0200 Subject: [PATCH] parent/child: Fix `_parent.type` validation. A `_parent` field can only point to a type that doesn't exist yet. The validation that checks this relied on have all mappings in the MapperService. The issue is that this check is performed on the elected master node and it may not have the IndexService at all to perform this check. In that case it creates a temporary IndexService and MapperService to perform mapping validation, but only the mappings that are part of the put index call are created, not the already existing mappings. Because of that the `_parent` field validation can't be performed. By changing the validation to rely on the cluster state's IndexMetaData instead we can get around the issue with the IndexService/MapperService on the elected master node. The IndexMetaData always holds the MappingMetaData instances for all types. --- .../cluster/metadata/MetaDataMappingService.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java b/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java index 3c2e77316ed..ae6f32edd13 100644 --- a/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java +++ b/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java @@ -19,6 +19,7 @@ package org.elasticsearch.cluster.metadata; +import com.carrotsearch.hppc.cursors.ObjectCursor; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -37,10 +38,10 @@ import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.Index; +import org.elasticsearch.index.IndexService; import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MergeMappingException; -import org.elasticsearch.index.IndexService; import org.elasticsearch.index.mapper.MergeResult; import org.elasticsearch.indices.IndexMissingException; import org.elasticsearch.indices.IndicesService; @@ -396,8 +397,11 @@ public class MetaDataMappingService extends AbstractComponent { // and a put mapping api call, so we don't which type did exist before. // Also the order of the mappings may be backwards. if (Version.indexCreated(indexService.getIndexSettings()).onOrAfter(Version.V_2_0_0) && newMapper.parentFieldMapper().active()) { - if (indexService.mapperService().types().contains(newMapper.parentFieldMapper().type())) { - throw new IllegalArgumentException("can't add a _parent field that points to an already existing type"); + IndexMetaData indexMetaData = currentState.metaData().index(index); + for (ObjectCursor mapping : indexMetaData.mappings().values()) { + if (newMapper.parentFieldMapper().type().equals(mapping.value.type())) { + throw new IllegalArgumentException("can't add a _parent field that points to an already existing type"); + } } } }