diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java index 739d831597a..14f9f500c45 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java @@ -259,9 +259,8 @@ public class MetaDataMappingService extends AbstractComponent { } else { newMapper = indexService.mapperService().parse(request.type(), mappingUpdateSource, existingMapper == null); if (existingMapper != null) { - // first, simulate - // this will just throw exceptions in case of problems - existingMapper.merge(newMapper.mapping(), true, request.updateAllTypes()); + // first, simulate: just call merge and ignore the result + existingMapper.merge(newMapper.mapping(), request.updateAllTypes()); } else { // TODO: can we find a better place for this validation? // The reason this validation is here is that the mapper service doesn't learn about diff --git a/core/src/main/java/org/elasticsearch/index/analysis/FieldNameAnalyzer.java b/core/src/main/java/org/elasticsearch/index/analysis/FieldNameAnalyzer.java index 68e3c3ee450..34829cedeed 100644 --- a/core/src/main/java/org/elasticsearch/index/analysis/FieldNameAnalyzer.java +++ b/core/src/main/java/org/elasticsearch/index/analysis/FieldNameAnalyzer.java @@ -23,36 +23,24 @@ import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.DelegatingAnalyzerWrapper; import org.elasticsearch.common.collect.CopyOnWriteHashMap; -import java.util.AbstractMap; import java.util.Map; -import java.util.stream.Stream; /** * */ public final class FieldNameAnalyzer extends DelegatingAnalyzerWrapper { - private final CopyOnWriteHashMap analyzers; - private final Analyzer defaultAnalyzer; + private final Map analyzers; - public FieldNameAnalyzer(Analyzer defaultAnalyzer) { - this(new CopyOnWriteHashMap<>(), defaultAnalyzer); - } - - public FieldNameAnalyzer(Map analyzers, Analyzer defaultAnalyzer) { + public FieldNameAnalyzer(Map analyzers) { super(Analyzer.PER_FIELD_REUSE_STRATEGY); this.analyzers = CopyOnWriteHashMap.copyOf(analyzers); - this.defaultAnalyzer = defaultAnalyzer; } public Map analyzers() { return analyzers; } - public Analyzer defaultAnalyzer() { - return defaultAnalyzer; - } - @Override protected Analyzer getWrappedAnalyzer(String fieldName) { Analyzer analyzer = analyzers.get(fieldName); @@ -63,18 +51,4 @@ public final class FieldNameAnalyzer extends DelegatingAnalyzerWrapper { // Fields need to be explicitly added throw new IllegalArgumentException("Field [" + fieldName + "] has no associated analyzer"); } - - /** - * Return a new instance that contains the union of this and of the provided analyzers. - */ - public FieldNameAnalyzer copyAndAddAll(Stream> mappers) { - CopyOnWriteHashMap result = analyzers.copyAndPutAll(mappers.map((e) -> { - if (e.getValue() == null) { - return new AbstractMap.SimpleImmutableEntry<>(e.getKey(), defaultAnalyzer); - } - return e; - })); - return new FieldNameAnalyzer(result, defaultAnalyzer); - } - } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/DocumentFieldMappers.java b/core/src/main/java/org/elasticsearch/index/mapper/DocumentFieldMappers.java index e14d7a0cd63..90da570bbe6 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentFieldMappers.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentFieldMappers.java @@ -20,15 +20,15 @@ package org.elasticsearch.index.mapper; import org.apache.lucene.analysis.Analyzer; -import org.elasticsearch.common.collect.CopyOnWriteHashMap; import org.elasticsearch.common.regex.Regex; -import org.elasticsearch.index.analysis.AnalysisService; import org.elasticsearch.index.analysis.FieldNameAnalyzer; -import java.util.AbstractMap; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.Map; import java.util.Set; /** @@ -37,44 +37,38 @@ import java.util.Set; public final class DocumentFieldMappers implements Iterable { /** Full field name to mapper */ - private final CopyOnWriteHashMap fieldMappers; + private final Map fieldMappers; private final FieldNameAnalyzer indexAnalyzer; private final FieldNameAnalyzer searchAnalyzer; private final FieldNameAnalyzer searchQuoteAnalyzer; - public DocumentFieldMappers(AnalysisService analysisService) { - this(new CopyOnWriteHashMap(), - new FieldNameAnalyzer(analysisService.defaultIndexAnalyzer()), - new FieldNameAnalyzer(analysisService.defaultSearchAnalyzer()), - new FieldNameAnalyzer(analysisService.defaultSearchQuoteAnalyzer())); - } - - private DocumentFieldMappers(CopyOnWriteHashMap fieldMappers, FieldNameAnalyzer indexAnalyzer, FieldNameAnalyzer searchAnalyzer, FieldNameAnalyzer searchQuoteAnalyzer) { - this.fieldMappers = fieldMappers; - this.indexAnalyzer = indexAnalyzer; - this.searchAnalyzer = searchAnalyzer; - this.searchQuoteAnalyzer = searchQuoteAnalyzer; - } - - public DocumentFieldMappers copyAndAllAll(Collection newMappers) { - CopyOnWriteHashMap map = this.fieldMappers; - for (FieldMapper fieldMapper : newMappers) { - map = map.copyAndPut(fieldMapper.fieldType().names().fullName(), fieldMapper); + private static void put(Map analyzers, String key, Analyzer value, Analyzer defaultValue) { + if (value == null) { + value = defaultValue; } - FieldNameAnalyzer indexAnalyzer = this.indexAnalyzer.copyAndAddAll(newMappers.stream().map((input) -> - new AbstractMap.SimpleImmutableEntry<>(input.fieldType().names().indexName(), (Analyzer)input.fieldType().indexAnalyzer()) - )); - FieldNameAnalyzer searchAnalyzer = this.searchAnalyzer.copyAndAddAll(newMappers.stream().map((input) -> - new AbstractMap.SimpleImmutableEntry<>(input.fieldType().names().indexName(), (Analyzer)input.fieldType().searchAnalyzer()) - )); - FieldNameAnalyzer searchQuoteAnalyzer = this.searchQuoteAnalyzer.copyAndAddAll(newMappers.stream().map((input) -> - new AbstractMap.SimpleImmutableEntry<>(input.fieldType().names().indexName(), (Analyzer) input.fieldType().searchQuoteAnalyzer()) - )); - return new DocumentFieldMappers(map,indexAnalyzer,searchAnalyzer,searchQuoteAnalyzer); + analyzers.put(key, value); } -/** Returns the mapper for the given field */ + public DocumentFieldMappers(Collection mappers, Analyzer defaultIndex, Analyzer defaultSearch, Analyzer defaultSearchQuote) { + Map fieldMappers = new HashMap<>(); + Map indexAnalyzers = new HashMap<>(); + Map searchAnalyzers = new HashMap<>(); + Map searchQuoteAnalyzers = new HashMap<>(); + for (FieldMapper mapper : mappers) { + fieldMappers.put(mapper.name(), mapper); + MappedFieldType fieldType = mapper.fieldType(); + put(indexAnalyzers, fieldType.names().indexName(), fieldType.indexAnalyzer(), defaultIndex); + put(searchAnalyzers, fieldType.names().indexName(), fieldType.searchAnalyzer(), defaultSearch); + put(searchQuoteAnalyzers, fieldType.names().indexName(), fieldType.searchQuoteAnalyzer(), defaultSearchQuote); + } + this.fieldMappers = Collections.unmodifiableMap(fieldMappers); + this.indexAnalyzer = new FieldNameAnalyzer(indexAnalyzers); + this.searchAnalyzer = new FieldNameAnalyzer(searchAnalyzers); + this.searchQuoteAnalyzer = new FieldNameAnalyzer(searchQuoteAnalyzers); + } + + /** Returns the mapper for the given field */ public FieldMapper getMapper(String field) { return fieldMappers.get(field); } @@ -112,14 +106,6 @@ public final class DocumentFieldMappers implements Iterable { return this.indexAnalyzer; } - /** - * A smart analyzer used for indexing that takes into account specific analyzers configured - * per {@link FieldMapper} with a custom default analyzer for no explicit field analyzer. - */ - public Analyzer indexAnalyzer(Analyzer defaultAnalyzer) { - return new FieldNameAnalyzer(indexAnalyzer.analyzers(), defaultAnalyzer); - } - /** * A smart analyzer used for searching that takes into account specific analyzers configured * per {@link FieldMapper}. diff --git a/core/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java index 756bd486316..c2d644d393d 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java @@ -24,16 +24,15 @@ import org.apache.lucene.search.Query; import org.apache.lucene.search.Scorer; import org.apache.lucene.search.Weight; import org.elasticsearch.ElasticsearchGenerationException; -import org.elasticsearch.Version; -import org.elasticsearch.common.Nullable; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.text.Text; -import org.elasticsearch.common.util.concurrent.ReleasableLock; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.IndexSettings; +import org.elasticsearch.index.analysis.AnalysisService; import org.elasticsearch.index.mapper.MetadataFieldMapper.TypeParser; import org.elasticsearch.index.mapper.internal.AllFieldMapper; import org.elasticsearch.index.mapper.internal.IdFieldMapper; @@ -51,15 +50,12 @@ import org.elasticsearch.search.internal.SearchContext; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.concurrent.locks.ReentrantReadWriteLock; import static java.util.Collections.emptyMap; @@ -72,16 +68,14 @@ public class DocumentMapper implements ToXContent { private Map, MetadataFieldMapper> metadataMappers = new LinkedHashMap<>(); - private final Settings indexSettings; - private final RootObjectMapper rootObjectMapper; private Map meta = emptyMap(); private final Mapper.BuilderContext builderContext; - public Builder(Settings indexSettings, RootObjectMapper.Builder builder, MapperService mapperService) { - this.indexSettings = indexSettings; + public Builder(RootObjectMapper.Builder builder, MapperService mapperService) { + final Settings indexSettings = mapperService.getIndexSettings().getSettings(); this.builderContext = new Mapper.BuilderContext(indexSettings, new ContentPath(1)); this.rootObjectMapper = builder.build(builderContext); @@ -104,9 +98,14 @@ public class DocumentMapper implements ToXContent { return this; } - public DocumentMapper build(MapperService mapperService, DocumentMapperParser docMapperParser) { + public DocumentMapper build(MapperService mapperService) { Objects.requireNonNull(rootObjectMapper, "Mapper builder must have the root object mapper set"); - return new DocumentMapper(mapperService, indexSettings, docMapperParser, rootObjectMapper, meta, metadataMappers, mapperService.mappingLock); + Mapping mapping = new Mapping( + mapperService.getIndexSettings().getIndexVersionCreated(), + rootObjectMapper, + metadataMappers.values().toArray(new MetadataFieldMapper[metadataMappers.values().size()]), + meta); + return new DocumentMapper(mapperService, mapping); } } @@ -115,38 +114,25 @@ public class DocumentMapper implements ToXContent { private final String type; private final Text typeText; - private volatile CompressedXContent mappingSource; + private final CompressedXContent mappingSource; - private volatile Mapping mapping; + private final Mapping mapping; private final DocumentParser documentParser; - private volatile DocumentFieldMappers fieldMappers; + private final DocumentFieldMappers fieldMappers; - private volatile Map objectMappers = Collections.emptyMap(); + private final Map objectMappers; - private boolean hasNestedObjects = false; + private final boolean hasNestedObjects; - private final ReleasableLock mappingWriteLock; - private final ReentrantReadWriteLock mappingLock; - - public DocumentMapper(MapperService mapperService, @Nullable Settings indexSettings, DocumentMapperParser docMapperParser, - RootObjectMapper rootObjectMapper, - Map meta, - Map, MetadataFieldMapper> metadataMappers, - ReentrantReadWriteLock mappingLock) { + public DocumentMapper(MapperService mapperService, Mapping mapping) { this.mapperService = mapperService; - this.type = rootObjectMapper.name(); + this.type = mapping.root().name(); this.typeText = new Text(this.type); - this.mapping = new Mapping( - Version.indexCreated(indexSettings), - rootObjectMapper, - metadataMappers.values().toArray(new MetadataFieldMapper[metadataMappers.values().size()]), - meta); - this.documentParser = new DocumentParser(indexSettings, docMapperParser, this, new ReleasableLock(mappingLock.readLock())); - - this.mappingWriteLock = new ReleasableLock(mappingLock.writeLock()); - this.mappingLock = mappingLock; + final IndexSettings indexSettings = mapperService.getIndexSettings(); + this.mapping = mapping; + this.documentParser = new DocumentParser(indexSettings, mapperService.documentMapperParser(), this); if (metadataMapper(ParentFieldMapper.class).active()) { // mark the routing field mapper as required @@ -163,7 +149,11 @@ public class DocumentMapper implements ToXContent { } MapperUtils.collect(this.mapping.root, newObjectMappers, newFieldMappers); - this.fieldMappers = new DocumentFieldMappers(docMapperParser.analysisService).copyAndAllAll(newFieldMappers); + final AnalysisService analysisService = mapperService.analysisService(); + this.fieldMappers = new DocumentFieldMappers(newFieldMappers, + analysisService.defaultIndexAnalyzer(), + analysisService.defaultSearchAnalyzer(), + analysisService.defaultSearchQuoteAnalyzer()); Map builder = new HashMap<>(); for (ObjectMapper objectMapper : newObjectMappers) { @@ -173,14 +163,20 @@ public class DocumentMapper implements ToXContent { } } + boolean hasNestedObjects = false; this.objectMappers = Collections.unmodifiableMap(builder); for (ObjectMapper objectMapper : newObjectMappers) { if (objectMapper.nested().isNested()) { hasNestedObjects = true; } } + this.hasNestedObjects = hasNestedObjects; - refreshSource(); + try { + mappingSource = new CompressedXContent(this, XContentType.JSON, ToXContent.EMPTY_PARAMS); + } catch (Exception e) { + throw new ElasticsearchGenerationException("failed to serialize source for type [" + type + "]", e); + } } public Mapping mapping() { @@ -334,46 +330,17 @@ public class DocumentMapper implements ToXContent { return mapperService.getParentTypes().contains(type); } - private void addMappers(Collection objectMappers, Collection fieldMappers, boolean updateAllTypes) { - assert mappingLock.isWriteLockedByCurrentThread(); - - // update mappers for this document type - Map builder = new HashMap<>(this.objectMappers); - for (ObjectMapper objectMapper : objectMappers) { - builder.put(objectMapper.fullPath(), objectMapper); - if (objectMapper.nested().isNested()) { - hasNestedObjects = true; - } - } - this.objectMappers = Collections.unmodifiableMap(builder); - this.fieldMappers = this.fieldMappers.copyAndAllAll(fieldMappers); - - // finally update for the entire index - mapperService.addMappers(type, objectMappers, fieldMappers); + public DocumentMapper merge(Mapping mapping, boolean updateAllTypes) { + Mapping merged = this.mapping.merge(mapping, updateAllTypes); + return new DocumentMapper(mapperService, merged); } - public void merge(Mapping mapping, boolean simulate, boolean updateAllTypes) { - try (ReleasableLock lock = mappingWriteLock.acquire()) { - mapperService.checkMappersCompatibility(type, mapping, updateAllTypes); - // do the merge even if simulate == false so that we get exceptions - Mapping merged = this.mapping.merge(mapping, updateAllTypes); - if (simulate == false) { - this.mapping = merged; - Collection objectMappers = new ArrayList<>(); - Collection fieldMappers = new ArrayList<>(Arrays.asList(merged.metadataMappers)); - MapperUtils.collect(merged.root, objectMappers, fieldMappers); - addMappers(objectMappers, fieldMappers, updateAllTypes); - refreshSource(); - } - } - } - - private void refreshSource() throws ElasticsearchGenerationException { - try { - mappingSource = new CompressedXContent(this, XContentType.JSON, ToXContent.EMPTY_PARAMS); - } catch (Exception e) { - throw new ElasticsearchGenerationException("failed to serialize source for type [" + type + "]", e); - } + /** + * Recursively update sub field types. + */ + public DocumentMapper updateFieldType(Map fullNameToFieldType) { + Mapping updated = this.mapping.updateFieldType(fullNameToFieldType); + return new DocumentMapper(mapperService, updated); } public void close() { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java b/core/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java index d7cc5eb8c93..7bb7b0b54a3 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java @@ -27,7 +27,6 @@ import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.Loggers; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentParser; @@ -46,7 +45,6 @@ import static org.elasticsearch.index.mapper.MapperBuilders.doc; public class DocumentMapperParser { - private final Settings indexSettings; final MapperService mapperService; final AnalysisService analysisService; private static final ESLogger logger = Loggers.getLogger(DocumentMapperParser.class); @@ -62,8 +60,7 @@ public class DocumentMapperParser { public DocumentMapperParser(IndexSettings indexSettings, MapperService mapperService, AnalysisService analysisService, SimilarityService similarityService, MapperRegistry mapperRegistry) { - this.indexSettings = indexSettings.getSettings(); - this.parseFieldMatcher = new ParseFieldMatcher(this.indexSettings); + this.parseFieldMatcher = new ParseFieldMatcher(indexSettings.getSettings()); this.mapperService = mapperService; this.analysisService = analysisService; this.similarityService = similarityService; @@ -110,7 +107,7 @@ public class DocumentMapperParser { Mapper.TypeParser.ParserContext parserContext = parserContext(type); // parse RootObjectMapper - DocumentMapper.Builder docBuilder = doc(indexSettings, (RootObjectMapper.Builder) rootObjectTypeParser.parse(type, mapping, parserContext), mapperService); + DocumentMapper.Builder docBuilder = doc((RootObjectMapper.Builder) rootObjectTypeParser.parse(type, mapping, parserContext), mapperService); Iterator> iterator = mapping.entrySet().iterator(); // parse DocumentMapper while(iterator.hasNext()) { @@ -137,7 +134,7 @@ public class DocumentMapperParser { checkNoRemainingFields(mapping, parserContext.indexVersionCreated(), "Root mapping definition has unsupported parameters: "); - return docBuilder.build(mapperService, this); + return docBuilder.build(mapperService); } public static void checkNoRemainingFields(String fieldName, Map fieldNodeMap, Version indexVersionCreated) { 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 bb1749d2336..4eb3100c99c 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java @@ -26,10 +26,9 @@ import org.apache.lucene.util.CloseableThreadLocal; import org.elasticsearch.Version; import org.elasticsearch.common.Strings; import org.elasticsearch.common.joda.FormatDateTimeFormatter; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.util.concurrent.ReleasableLock; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.index.IndexSettings; import org.elasticsearch.index.mapper.core.DateFieldMapper.DateFieldType; import org.elasticsearch.index.mapper.core.NumberFieldMapper; import org.elasticsearch.index.mapper.core.StringFieldMapper; @@ -53,29 +52,21 @@ class DocumentParser implements Closeable { private CloseableThreadLocal cache = new CloseableThreadLocal() { @Override protected ParseContext.InternalParseContext initialValue() { - return new ParseContext.InternalParseContext(indexSettings, docMapperParser, docMapper, new ContentPath(0)); + return new ParseContext.InternalParseContext(indexSettings.getSettings(), docMapperParser, docMapper, new ContentPath(0)); } }; - private final Settings indexSettings; + private final IndexSettings indexSettings; private final DocumentMapperParser docMapperParser; private final DocumentMapper docMapper; - private final ReleasableLock parseLock; - public DocumentParser(Settings indexSettings, DocumentMapperParser docMapperParser, DocumentMapper docMapper, ReleasableLock parseLock) { + public DocumentParser(IndexSettings indexSettings, DocumentMapperParser docMapperParser, DocumentMapper docMapper) { this.indexSettings = indexSettings; this.docMapperParser = docMapperParser; this.docMapper = docMapper; - this.parseLock = parseLock; } public ParsedDocument parseDocument(SourceToParse source) throws MapperParsingException { - try (ReleasableLock lock = parseLock.acquire()){ - return innerParseDocument(source); - } - } - - private ParsedDocument innerParseDocument(SourceToParse source) throws MapperParsingException { if (docMapper.type().equals(MapperService.DEFAULT_MAPPING)) { throw new IllegalArgumentException("It is forbidden to index into the default mapping [" + MapperService.DEFAULT_MAPPING + "]"); } @@ -132,7 +123,7 @@ class DocumentParser implements Closeable { // try to parse the next token, this should be null if the object is ended properly // but will throw a JSON exception if the extra tokens is not valid JSON (this will be handled by the catch) - if (Version.indexCreated(indexSettings).onOrAfter(Version.V_2_0_0_beta1) + if (indexSettings.getIndexVersionCreated().onOrAfter(Version.V_2_0_0_beta1) && source.parser() == null && parser != null) { // only check for end of tokens if we created the parser here token = parser.nextToken(); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java index 93de39d0f9e..9c77a416bf1 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java @@ -44,6 +44,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.stream.StreamSupport; public abstract class FieldMapper extends Mapper implements Cloneable { @@ -267,7 +268,7 @@ public abstract class FieldMapper extends Mapper implements Cloneable { } } - protected MappedFieldTypeReference fieldTypeRef; + protected MappedFieldType fieldType; protected final MappedFieldType defaultFieldType; protected MultiFields multiFields; protected CopyTo copyTo; @@ -277,7 +278,8 @@ public abstract class FieldMapper extends Mapper implements Cloneable { super(simpleName); assert indexSettings != null; this.indexCreatedBefore2x = Version.indexCreated(indexSettings).before(Version.V_2_0_0_beta1); - this.fieldTypeRef = new MappedFieldTypeReference(fieldType); // the reference ctor freezes the field type + fieldType.freeze(); + this.fieldType = fieldType; defaultFieldType.freeze(); this.defaultFieldType = defaultFieldType; this.multiFields = multiFields; @@ -290,23 +292,7 @@ public abstract class FieldMapper extends Mapper implements Cloneable { } public MappedFieldType fieldType() { - return fieldTypeRef.get(); - } - - /** Returns a reference to the MappedFieldType for this mapper. */ - public MappedFieldTypeReference fieldTypeReference() { - return fieldTypeRef; - } - - /** - * Updates the reference to this field's MappedFieldType. - * Implementations should assert equality of the underlying field type - */ - public void setFieldTypeReference(MappedFieldTypeReference ref) { - if (ref.get().equals(fieldType()) == false) { - throw new IllegalStateException("Cannot overwrite field type reference to unequal reference"); - } - this.fieldTypeRef = ref; + return fieldType; } /** @@ -350,10 +336,8 @@ public abstract class FieldMapper extends Mapper implements Cloneable { return false; } + @Override public Iterator iterator() { - if (multiFields == null) { - return Collections.emptyIterator(); - } return multiFields.iterator(); } @@ -389,12 +373,26 @@ public abstract class FieldMapper extends Mapper implements Cloneable { multiFields = multiFields.merge(fieldMergeWith.multiFields); // apply changeable values - MappedFieldType fieldType = fieldMergeWith.fieldType().clone(); - fieldType.freeze(); - fieldTypeRef.set(fieldType); + this.fieldType = fieldMergeWith.fieldType; this.copyTo = fieldMergeWith.copyTo; } + @Override + public FieldMapper updateFieldType(Map fullNameToFieldType) { + final MappedFieldType newFieldType = fullNameToFieldType.get(fieldType.names().fullName()); + if (newFieldType == null) { + throw new IllegalStateException(); + } + MultiFields updatedMultiFields = multiFields.updateFieldType(fullNameToFieldType); + if (fieldType == newFieldType && multiFields == updatedMultiFields) { + return this; // no change + } + FieldMapper updated = clone(); + updated.fieldType = newFieldType; + updated.multiFields = updatedMultiFields; + return updated; + } + @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(simpleName()); @@ -619,6 +617,27 @@ public abstract class FieldMapper extends Mapper implements Cloneable { return new MultiFields(mappers); } + public MultiFields updateFieldType(Map fullNameToFieldType) { + ImmutableOpenMap.Builder newMappersBuilder = null; + + for (ObjectCursor cursor : mappers.values()) { + FieldMapper updated = cursor.value.updateFieldType(fullNameToFieldType); + if (updated != cursor.value) { + if (newMappersBuilder == null) { + newMappersBuilder = ImmutableOpenMap.builder(mappers); + } + newMappersBuilder.put(updated.simpleName(), updated); + } + } + + if (newMappersBuilder == null) { + return this; + } + + ImmutableOpenMap mappers = newMappersBuilder.build(); + return new MultiFields(mappers); + } + public Iterator iterator() { return StreamSupport.stream(mappers.values().spliterator(), false).map((p) -> (Mapper)p.value).iterator(); } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java b/core/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java index da21e599cc9..e06b4e799ed 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java @@ -37,16 +37,16 @@ import java.util.Set; class FieldTypeLookup implements Iterable { /** Full field name to field type */ - private final CopyOnWriteHashMap fullNameToFieldType; + final CopyOnWriteHashMap fullNameToFieldType; /** Full field name to types containing a mapping for this full name. */ - private final CopyOnWriteHashMap> fullNameToTypes; + final CopyOnWriteHashMap> fullNameToTypes; /** Index field name to field type */ - private final CopyOnWriteHashMap indexNameToFieldType; + final CopyOnWriteHashMap indexNameToFieldType; /** Index field name to types containing a mapping for this index name. */ - private final CopyOnWriteHashMap> indexNameToTypes; + final CopyOnWriteHashMap> indexNameToTypes; /** Create a new empty instance. */ public FieldTypeLookup() { @@ -57,9 +57,9 @@ class FieldTypeLookup implements Iterable { } private FieldTypeLookup( - CopyOnWriteHashMap fullName, + CopyOnWriteHashMap fullName, CopyOnWriteHashMap> fullNameToTypes, - CopyOnWriteHashMap indexName, + CopyOnWriteHashMap indexName, CopyOnWriteHashMap> indexNameToTypes) { this.fullNameToFieldType = fullName; this.fullNameToTypes = fullNameToTypes; @@ -89,43 +89,35 @@ class FieldTypeLookup implements Iterable { * from the provided fields. If a field already exists, the field type will be updated * to use the new mappers field type. */ - public FieldTypeLookup copyAndAddAll(String type, Collection newFieldMappers) { + public FieldTypeLookup copyAndAddAll(String type, Collection fieldMappers, boolean updateAllTypes) { Objects.requireNonNull(type, "type must not be null"); if (MapperService.DEFAULT_MAPPING.equals(type)) { throw new IllegalArgumentException("Default mappings should not be added to the lookup"); } - CopyOnWriteHashMap fullName = this.fullNameToFieldType; + + CopyOnWriteHashMap fullName = this.fullNameToFieldType; CopyOnWriteHashMap> fullNameToTypes = this.fullNameToTypes; - CopyOnWriteHashMap indexName = this.indexNameToFieldType; + CopyOnWriteHashMap indexName = this.indexNameToFieldType; CopyOnWriteHashMap> indexNameToTypes = this.indexNameToTypes; - for (FieldMapper fieldMapper : newFieldMappers) { + for (FieldMapper fieldMapper : fieldMappers) { MappedFieldType fieldType = fieldMapper.fieldType(); - MappedFieldTypeReference fullNameRef = fullName.get(fieldType.names().fullName()); - MappedFieldTypeReference indexNameRef = indexName.get(fieldType.names().indexName()); - if (fullNameRef == null && indexNameRef == null) { - // new field, just use the ref from this field mapper - fullName = fullName.copyAndPut(fieldType.names().fullName(), fieldMapper.fieldTypeReference()); - indexName = indexName.copyAndPut(fieldType.names().indexName(), fieldMapper.fieldTypeReference()); - } else if (fullNameRef == null) { - // this index name already exists, so copy over the reference - fullName = fullName.copyAndPut(fieldType.names().fullName(), indexNameRef); - indexNameRef.set(fieldMapper.fieldType()); // field type is updated, since modifiable settings may have changed - fieldMapper.setFieldTypeReference(indexNameRef); - } else if (indexNameRef == null) { - // this full name already exists, so copy over the reference - indexName = indexName.copyAndPut(fieldType.names().indexName(), fullNameRef); - fullNameRef.set(fieldMapper.fieldType()); // field type is updated, since modifiable settings may have changed - fieldMapper.setFieldTypeReference(fullNameRef); - } else if (fullNameRef == indexNameRef) { - // the field already exists, so replace the reference in this mapper with the pre-existing one - fullNameRef.set(fieldMapper.fieldType()); // field type is updated, since modifiable settings may have changed - fieldMapper.setFieldTypeReference(fullNameRef); - } else { + MappedFieldType fullNameFieldType = fullName.get(fieldType.names().fullName()); + MappedFieldType indexNameFieldType = indexName.get(fieldType.names().indexName()); + + if (fullNameFieldType != null && indexNameFieldType != null && fullNameFieldType != indexNameFieldType) { // this new field bridges between two existing field names (a full and index name), which we cannot support throw new IllegalStateException("insane mappings found. field " + fieldType.names().fullName() + " maps across types to field " + fieldType.names().indexName()); } + // is the update even legal? + checkCompatibility(type, fieldMapper, updateAllTypes); + + if (fieldType != fullNameFieldType || fieldType != indexNameFieldType) { + fullName = fullName.copyAndPut(fieldType.names().fullName(), fieldMapper.fieldType()); + indexName = indexName.copyAndPut(fieldType.names().indexName(), fieldMapper.fieldType()); + } + fullNameToTypes = addType(fullNameToTypes, fieldType.names().fullName(), type); indexNameToTypes = addType(indexNameToTypes, fieldType.names().indexName(), type); } @@ -145,42 +137,38 @@ class FieldTypeLookup implements Iterable { } /** - * Checks if the given mappers' field types are compatible with existing field types. - * If any are not compatible, an IllegalArgumentException is thrown. + * Checks if the given field type is compatible with an existing field type. + * An IllegalArgumentException is thrown in case of incompatibility. * If updateAllTypes is true, only basic compatibility is checked. */ - public void checkCompatibility(String type, Collection fieldMappers, boolean updateAllTypes) { - for (FieldMapper fieldMapper : fieldMappers) { - MappedFieldTypeReference ref = fullNameToFieldType.get(fieldMapper.fieldType().names().fullName()); - if (ref != null) { - List conflicts = new ArrayList<>(); - final Set types = fullNameToTypes.get(fieldMapper.fieldType().names().fullName()); - boolean strict = beStrict(type, types, updateAllTypes); - ref.get().checkCompatibility(fieldMapper.fieldType(), conflicts, strict); - if (conflicts.isEmpty() == false) { - throw new IllegalArgumentException("Mapper for [" + fieldMapper.fieldType().names().fullName() + "] conflicts with existing mapping in other types:\n" + conflicts.toString()); - } + private void checkCompatibility(String type, FieldMapper fieldMapper, boolean updateAllTypes) { + MappedFieldType fieldType = fullNameToFieldType.get(fieldMapper.fieldType().names().fullName()); + if (fieldType != null) { + List conflicts = new ArrayList<>(); + final Set types = fullNameToTypes.get(fieldMapper.fieldType().names().fullName()); + boolean strict = beStrict(type, types, updateAllTypes); + fieldType.checkCompatibility(fieldMapper.fieldType(), conflicts, strict); + if (conflicts.isEmpty() == false) { + throw new IllegalArgumentException("Mapper for [" + fieldMapper.fieldType().names().fullName() + "] conflicts with existing mapping in other types:\n" + conflicts.toString()); } + } - // field type for the index name must be compatible too - MappedFieldTypeReference indexNameRef = indexNameToFieldType.get(fieldMapper.fieldType().names().indexName()); - if (indexNameRef != null) { - List conflicts = new ArrayList<>(); - final Set types = indexNameToTypes.get(fieldMapper.fieldType().names().indexName()); - boolean strict = beStrict(type, types, updateAllTypes); - indexNameRef.get().checkCompatibility(fieldMapper.fieldType(), conflicts, strict); - if (conflicts.isEmpty() == false) { - throw new IllegalArgumentException("Mapper for [" + fieldMapper.fieldType().names().fullName() + "] conflicts with mapping with the same index name in other types" + conflicts.toString()); - } + // field type for the index name must be compatible too + fieldType = indexNameToFieldType.get(fieldMapper.fieldType().names().indexName()); + if (fieldType != null) { + List conflicts = new ArrayList<>(); + final Set types = indexNameToTypes.get(fieldMapper.fieldType().names().indexName()); + boolean strict = beStrict(type, types, updateAllTypes); + fieldType.checkCompatibility(fieldMapper.fieldType(), conflicts, strict); + if (conflicts.isEmpty() == false) { + throw new IllegalArgumentException("Mapper for [" + fieldMapper.fieldType().names().fullName() + "] conflicts with mapping with the same index name in other types" + conflicts.toString()); } } } /** Returns the field for the given field */ public MappedFieldType get(String field) { - MappedFieldTypeReference ref = fullNameToFieldType.get(field); - if (ref == null) return null; - return ref.get(); + return fullNameToFieldType.get(field); } /** Get the set of types that have a mapping for the given field. */ @@ -194,9 +182,7 @@ class FieldTypeLookup implements Iterable { /** Returns the field type for the given index name */ public MappedFieldType getByIndexName(String field) { - MappedFieldTypeReference ref = indexNameToFieldType.get(field); - if (ref == null) return null; - return ref.get(); + return indexNameToFieldType.get(field); } /** Get the set of types that have a mapping for the given field. */ @@ -238,7 +224,8 @@ class FieldTypeLookup implements Iterable { return fields; } + @Override public Iterator iterator() { - return fullNameToFieldType.values().stream().map((p) -> p.get()).iterator(); + return fullNameToFieldType.values().iterator(); } } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldTypeReference.java b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldTypeReference.java deleted file mode 100644 index 1a9d0b70b37..00000000000 --- a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldTypeReference.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.elasticsearch.index.mapper; - -/** - * A container for a {@link MappedFieldType} which can be updated and is reference counted. - */ -public class MappedFieldTypeReference { - private MappedFieldType fieldType; // the current field type this reference points to - - public MappedFieldTypeReference(MappedFieldType fieldType) { - fieldType.freeze(); // ensure frozen - this.fieldType = fieldType; - } - - public MappedFieldType get() { - return fieldType; - } - - public void set(MappedFieldType fieldType) { - fieldType.freeze(); // ensure frozen - this.fieldType = fieldType; - } - -} diff --git a/core/src/main/java/org/elasticsearch/index/mapper/Mapper.java b/core/src/main/java/org/elasticsearch/index/mapper/Mapper.java index 4c3aa3c56bb..ffdae90c436 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/Mapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/Mapper.java @@ -177,4 +177,11 @@ public abstract class Mapper implements ToXContent, Iterable { /** Return the merge of {@code mergeWith} into this. * Both {@code this} and {@code mergeWith} will be left unmodified. */ public abstract Mapper merge(Mapper mergeWith, boolean updateAllTypes); + + /** + * Update the field type of this mapper. This is necessary because some mapping updates + * can modify mappings across several types. This method must return a copy of the mapper + * so that the current mapper is not modified. + */ + public abstract Mapper updateFieldType(Map fullNameToFieldType); } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MapperBuilders.java b/core/src/main/java/org/elasticsearch/index/mapper/MapperBuilders.java index 75d2cb43937..9ea9e99f01b 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/MapperBuilders.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MapperBuilders.java @@ -19,7 +19,6 @@ package org.elasticsearch.index.mapper; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.mapper.core.BinaryFieldMapper; import org.elasticsearch.index.mapper.core.BooleanFieldMapper; import org.elasticsearch.index.mapper.core.ByteFieldMapper; @@ -41,8 +40,8 @@ public final class MapperBuilders { private MapperBuilders() {} - public static DocumentMapper.Builder doc(Settings settings, RootObjectMapper.Builder objectBuilder, MapperService mapperService) { - return new DocumentMapper.Builder(settings, objectBuilder, mapperService); + public static DocumentMapper.Builder doc(RootObjectMapper.Builder objectBuilder, MapperService mapperService) { + return new DocumentMapper.Builder(objectBuilder, mapperService); } public static RootObjectMapper.Builder rootObject(String name) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java b/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java index c3622b4a5b8..afaaca1b1ca 100755 --- a/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java @@ -35,11 +35,9 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.ElasticsearchGenerationException; import org.elasticsearch.Version; import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.regex.Regex; -import org.elasticsearch.common.util.concurrent.ReleasableLock; import org.elasticsearch.index.AbstractIndexComponent; import org.elasticsearch.index.IndexSettings; import org.elasticsearch.index.analysis.AnalysisService; @@ -65,7 +63,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; import java.util.stream.Collectors; @@ -98,12 +95,6 @@ public class MapperService extends AbstractIndexComponent implements Closeable { private volatile Map mappers = emptyMap(); - // A lock for mappings: modifications (put mapping) need to be performed - // under the write lock and read operations (document parsing) need to be - // performed under the read lock - final ReentrantReadWriteLock mappingLock = new ReentrantReadWriteLock(); - private final ReleasableLock mappingWriteLock = new ReleasableLock(mappingLock.writeLock()); - private volatile FieldTypeLookup fieldTypes; private volatile Map fullPathObjectMappers = new HashMap<>(); private boolean hasNested = false; // updated dynamically to true when a nested object is added @@ -216,7 +207,7 @@ public class MapperService extends AbstractIndexComponent implements Closeable { DocumentMapper mapper = documentParser.parse(type, mappingSource); // still add it as a document mapper so we have it registered and, for example, persisted back into // the cluster meta data if needed, or checked for existence - try (ReleasableLock lock = mappingWriteLock.acquire()) { + synchronized (this) { mappers = newMapBuilder(mappers).put(type, mapper).map(); } try { @@ -226,7 +217,7 @@ public class MapperService extends AbstractIndexComponent implements Closeable { } return mapper; } else { - try (ReleasableLock lock = mappingWriteLock.acquire()) { + synchronized (this) { // only apply the default mapping if we don't have the type yet applyDefault &= mappers.containsKey(type) == false; return merge(parse(type, mappingSource, applyDefault), updateAllTypes); @@ -234,9 +225,7 @@ public class MapperService extends AbstractIndexComponent implements Closeable { } } - // never expose this to the outside world, we need to reparse the doc mapper so we get fresh - // instances of field mappers to properly remove existing doc mapper - private DocumentMapper merge(DocumentMapper mapper, boolean updateAllTypes) { + private synchronized DocumentMapper merge(DocumentMapper mapper, boolean updateAllTypes) { if (mapper.type().length() == 0) { throw new InvalidTypeNameException("mapping type name is empty"); } @@ -262,34 +251,89 @@ public class MapperService extends AbstractIndexComponent implements Closeable { logger.warn("Type [{}] starts with a '.', it is recommended not to start a type name with a '.'", mapper.type()); } } - // we can add new field/object mappers while the old ones are there - // since we get new instances of those, and when we remove, we remove - // by instance equality + + // 1. compute the merged DocumentMapper DocumentMapper oldMapper = mappers.get(mapper.type()); - + DocumentMapper newMapper; if (oldMapper != null) { - oldMapper.merge(mapper.mapping(), false, updateAllTypes); - return oldMapper; + newMapper = oldMapper.merge(mapper.mapping(), updateAllTypes); } else { - Tuple, Collection> newMappers = checkMappersCompatibility( - mapper.type(), mapper.mapping(), updateAllTypes); - Collection newObjectMappers = newMappers.v1(); - Collection newFieldMappers = newMappers.v2(); - addMappers(mapper.type(), newObjectMappers, newFieldMappers); + newMapper = mapper; + } + // 2. check basic sanity of the new mapping + List objectMappers = new ArrayList<>(); + List fieldMappers = new ArrayList<>(); + Collections.addAll(fieldMappers, newMapper.mapping().metadataMappers); + MapperUtils.collect(newMapper.mapping().root(), objectMappers, fieldMappers); + checkFieldUniqueness(newMapper.type(), objectMappers, fieldMappers); + checkObjectsCompatibility(newMapper.type(), objectMappers, fieldMappers, updateAllTypes); + + // 3. update lookup data-structures + // this will in particular make sure that the merged fields are compatible with other types + FieldTypeLookup fieldTypes = this.fieldTypes.copyAndAddAll(newMapper.type(), fieldMappers, updateAllTypes); + + boolean hasNested = this.hasNested; + Map fullPathObjectMappers = new HashMap<>(this.fullPathObjectMappers); + for (ObjectMapper objectMapper : objectMappers) { + fullPathObjectMappers.put(objectMapper.fullPath(), objectMapper); + if (objectMapper.nested().isNested()) { + hasNested = true; + } + } + fullPathObjectMappers = Collections.unmodifiableMap(fullPathObjectMappers); + Set parentTypes = this.parentTypes; + if (oldMapper == null && newMapper.parentFieldMapper().active()) { + parentTypes = new HashSet<>(parentTypes.size() + 1); + parentTypes.addAll(this.parentTypes); + parentTypes.add(mapper.parentFieldMapper().type()); + parentTypes = Collections.unmodifiableSet(parentTypes); + } + + Map mappers = new HashMap<>(this.mappers); + mappers.put(newMapper.type(), newMapper); + for (Map.Entry entry : mappers.entrySet()) { + if (entry.getKey().equals(DEFAULT_MAPPING)) { + continue; + } + DocumentMapper m = entry.getValue(); + // apply changes to the field types back + m = m.updateFieldType(fieldTypes.fullNameToFieldType); + entry.setValue(m); + } + mappers = Collections.unmodifiableMap(mappers); + + // 4. commit the change + this.mappers = mappers; + this.fieldTypes = fieldTypes; + this.hasNested = hasNested; + this.fullPathObjectMappers = fullPathObjectMappers; + this.parentTypes = parentTypes; + + // 5. send notifications about the change + if (oldMapper == null) { + // means the mapping was created for (DocumentTypeListener typeListener : typeListeners) { typeListener.beforeCreate(mapper); } - mappers = newMapBuilder(mappers).put(mapper.type(), mapper).map(); - if (mapper.parentFieldMapper().active()) { - Set newParentTypes = new HashSet<>(parentTypes.size() + 1); - newParentTypes.addAll(parentTypes); - newParentTypes.add(mapper.parentFieldMapper().type()); - parentTypes = unmodifiableSet(newParentTypes); - } - assert assertSerialization(mapper); - return mapper; } + + assert assertSerialization(newMapper); + assert assertMappersShareSameFieldType(); + + return newMapper; + } + + private boolean assertMappersShareSameFieldType() { + for (DocumentMapper mapper : docMappers(false)) { + List fieldMappers = new ArrayList<>(); + Collections.addAll(fieldMappers, mapper.mapping().metadataMappers); + MapperUtils.collect(mapper.root(), new ArrayList(), fieldMappers); + for (FieldMapper fieldMapper : fieldMappers) { + assert fieldMapper.fieldType() == fieldTypes.get(fieldMapper.name()) : fieldMapper.name(); + } + } + return true; } private boolean typeNameStartsWithIllegalDot(DocumentMapper mapper) { @@ -339,8 +383,8 @@ public class MapperService extends AbstractIndexComponent implements Closeable { } } - protected void checkMappersCompatibility(String type, Collection objectMappers, Collection fieldMappers, boolean updateAllTypes) { - assert mappingLock.isWriteLockedByCurrentThread(); + private void checkObjectsCompatibility(String type, Collection objectMappers, Collection fieldMappers, boolean updateAllTypes) { + assert Thread.holdsLock(this); checkFieldUniqueness(type, objectMappers, fieldMappers); @@ -358,31 +402,6 @@ public class MapperService extends AbstractIndexComponent implements Closeable { throw new IllegalArgumentException("Field [" + fieldMapper.name() + "] is defined as a field in mapping [" + type + "] but this name is already used for an object in other types"); } } - - fieldTypes.checkCompatibility(type, fieldMappers, updateAllTypes); - } - - protected Tuple, Collection> checkMappersCompatibility( - String type, Mapping mapping, boolean updateAllTypes) { - List objectMappers = new ArrayList<>(); - List fieldMappers = new ArrayList<>(); - Collections.addAll(fieldMappers, mapping.metadataMappers); - MapperUtils.collect(mapping.root, objectMappers, fieldMappers); - checkMappersCompatibility(type, objectMappers, fieldMappers, updateAllTypes); - return new Tuple<>(objectMappers, fieldMappers); - } - - protected void addMappers(String type, Collection objectMappers, Collection fieldMappers) { - assert mappingLock.isWriteLockedByCurrentThread(); - Map fullPathObjectMappers = new HashMap<>(this.fullPathObjectMappers); - for (ObjectMapper objectMapper : objectMappers) { - fullPathObjectMappers.put(objectMapper.fullPath(), objectMapper); - if (objectMapper.nested().isNested()) { - hasNested = true; - } - } - this.fullPathObjectMappers = Collections.unmodifiableMap(fullPathObjectMappers); - this.fieldTypes = this.fieldTypes.copyAndAddAll(type, fieldMappers); } public DocumentMapper parse(String mappingType, CompressedXContent mappingSource, boolean applyDefault) throws MapperParsingException { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/Mapping.java b/core/src/main/java/org/elasticsearch/index/mapper/Mapping.java index d33a97a4151..25ea4b7d398 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/Mapping.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/Mapping.java @@ -93,7 +93,7 @@ public final class Mapping implements ToXContent { return (T) metadataMappersMap.get(clazz); } - /** @see DocumentMapper#merge(Mapping, boolean, boolean) */ + /** @see DocumentMapper#merge(Mapping, boolean) */ public Mapping merge(Mapping mergeWith, boolean updateAllTypes) { RootObjectMapper mergedRoot = root.merge(mergeWith.root, updateAllTypes); Map, MetadataFieldMapper> mergedMetaDataMappers = new HashMap<>(metadataMappersMap); @@ -110,6 +110,18 @@ public final class Mapping implements ToXContent { return new Mapping(indexCreated, mergedRoot, mergedMetaDataMappers.values().toArray(new MetadataFieldMapper[0]), mergeWith.meta); } + /** + * Recursively update sub field types. + */ + public Mapping updateFieldType(Map fullNameToFieldType) { + final MetadataFieldMapper[] updatedMeta = Arrays.copyOf(metadataMappers, metadataMappers.length); + for (int i = 0; i < updatedMeta.length; ++i) { + updatedMeta[i] = (MetadataFieldMapper) updatedMeta[i].updateFieldType(fullNameToFieldType); + } + RootObjectMapper updatedRoot = root.updateFieldType(fullNameToFieldType); + return new Mapping(indexCreated, updatedRoot, updatedMeta, meta); + } + @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { root.toXContent(builder, params, new ToXContent() { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/geo/BaseGeoPointFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/geo/BaseGeoPointFieldMapper.java index 6f413683d63..79261ec3809 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/geo/BaseGeoPointFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/geo/BaseGeoPointFieldMapper.java @@ -346,11 +346,11 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr } } - protected final DoubleFieldMapper latMapper; + protected DoubleFieldMapper latMapper; - protected final DoubleFieldMapper lonMapper; + protected DoubleFieldMapper lonMapper; - protected final StringFieldMapper geoHashMapper; + protected StringFieldMapper geoHashMapper; protected Explicit ignoreMalformed; @@ -504,4 +504,25 @@ public abstract class BaseGeoPointFieldMapper extends FieldMapper implements Arr builder.field(Names.IGNORE_MALFORMED, ignoreMalformed.value()); } } + + @Override + public FieldMapper updateFieldType(Map fullNameToFieldType) { + BaseGeoPointFieldMapper updated = (BaseGeoPointFieldMapper) super.updateFieldType(fullNameToFieldType); + StringFieldMapper geoUpdated = geoHashMapper == null ? null : (StringFieldMapper) geoHashMapper.updateFieldType(fullNameToFieldType); + DoubleFieldMapper latUpdated = latMapper == null ? null : (DoubleFieldMapper) latMapper.updateFieldType(fullNameToFieldType); + DoubleFieldMapper lonUpdated = lonMapper == null ? null : (DoubleFieldMapper) lonMapper.updateFieldType(fullNameToFieldType); + if (updated == this + && geoUpdated == geoHashMapper + && latUpdated == latMapper + && lonUpdated == lonMapper) { + return this; + } + if (updated == this) { + updated = (BaseGeoPointFieldMapper) updated.clone(); + } + updated.geoHashMapper = geoUpdated; + updated.latMapper = latUpdated; + updated.lonMapper = lonUpdated; + return updated; + } } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/FieldNamesFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/FieldNamesFieldMapper.java index e03439f3f54..d8d61f4bab3 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/FieldNamesFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/FieldNamesFieldMapper.java @@ -216,7 +216,7 @@ public class FieldNamesFieldMapper extends MetadataFieldMapper { FieldNamesFieldType newFieldType = fieldType().clone(); newFieldType.setEnabled(false); newFieldType.freeze(); - fieldTypeRef.set(newFieldType); + this.fieldType = newFieldType; } } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java index e82ecf0097a..9fdb9b586e4 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java @@ -95,8 +95,8 @@ public class TimestampFieldMapper extends MetadataFieldMapper { private boolean explicitStore = false; private Boolean ignoreMissing = null; - public Builder(MappedFieldType existing) { - super(Defaults.NAME, existing == null ? Defaults.FIELD_TYPE : existing, Defaults.FIELD_TYPE); + public Builder(MappedFieldType existing, Settings settings) { + super(Defaults.NAME, existing == null ? Defaults.FIELD_TYPE : existing, chooseFieldType(settings, null)); if (existing != null) { // if there is an existing type, always use that store value (only matters for < 2.0) explicitStore = true; @@ -167,7 +167,7 @@ public class TimestampFieldMapper extends MetadataFieldMapper { public static class TypeParser implements MetadataFieldMapper.TypeParser { @Override public MetadataFieldMapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - Builder builder = new Builder(parserContext.mapperService().fullName(NAME)); + Builder builder = new Builder(parserContext.mapperService().fullName(NAME), parserContext.mapperService().getIndexSettings().getSettings()); if (parserContext.indexVersionCreated().before(Version.V_2_0_0_beta1)) { parseField(builder, builder.name, node, parserContext); } @@ -260,7 +260,7 @@ public class TimestampFieldMapper extends MetadataFieldMapper { private final Boolean ignoreMissing; private TimestampFieldMapper(Settings indexSettings, MappedFieldType existing) { - this(chooseFieldType(indexSettings, existing).clone(), chooseFieldType(indexSettings, null), Defaults.ENABLED, Defaults.PATH, Defaults.DEFAULT_TIMESTAMP, null, indexSettings); + this(chooseFieldType(indexSettings, existing).clone(), chooseFieldType(indexSettings, null).clone(), Defaults.ENABLED, Defaults.PATH, Defaults.DEFAULT_TIMESTAMP, null, indexSettings); } private TimestampFieldMapper(MappedFieldType fieldType, MappedFieldType defaultFieldType, EnabledAttributeMapper enabledState, String path, diff --git a/core/src/main/java/org/elasticsearch/index/mapper/object/ObjectMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/object/ObjectMapper.java index 519ac0f5e24..9f3b503ab49 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/object/ObjectMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/object/ObjectMapper.java @@ -31,6 +31,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.mapper.DocumentMapperParser; +import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.index.mapper.MapperParsingException; import org.elasticsearch.index.mapper.MetadataFieldMapper; @@ -493,6 +494,28 @@ public class ObjectMapper extends Mapper implements AllFieldMapper.IncludeInAll, } } + @Override + public ObjectMapper updateFieldType(Map fullNameToFieldType) { + List updatedMappers = null; + for (Mapper mapper : this) { + Mapper updated = mapper.updateFieldType(fullNameToFieldType); + if (mapper != updated) { + if (updatedMappers == null) { + updatedMappers = new ArrayList<>(); + } + updatedMappers.add(updated); + } + } + if (updatedMappers == null) { + return this; + } + ObjectMapper updated = clone(); + for (Mapper updatedMapper : updatedMappers) { + updated.putMapper(updatedMapper); + } + return updated; + } + @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { toXContent(builder, params, null); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/object/RootObjectMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/object/RootObjectMapper.java index 90030d40a05..8183a2179a2 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/object/RootObjectMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/object/RootObjectMapper.java @@ -27,6 +27,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.mapper.ContentPath; +import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.index.mapper.MapperParsingException; import org.elasticsearch.index.mapper.ParseContext; @@ -295,6 +296,11 @@ public class RootObjectMapper extends ObjectMapper { this.dynamicTemplates = mergedTemplates.toArray(new DynamicTemplate[mergedTemplates.size()]); } + @Override + public RootObjectMapper updateFieldType(Map fullNameToFieldType) { + return (RootObjectMapper) super.updateFieldType(fullNameToFieldType); + } + @Override protected void doXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { if (dynamicDateTimeFormatters != Defaults.DYNAMIC_DATE_TIME_FORMATTERS) { diff --git a/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java b/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java index 13fce88e2c1..889cf74a7b4 100644 --- a/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java +++ b/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java @@ -1931,9 +1931,8 @@ public class InternalEngineTests extends ESTestCase { SimilarityService similarityService = new SimilarityService(indexSettings, Collections.emptyMap()); MapperRegistry mapperRegistry = new IndicesModule().getMapperRegistry(); MapperService mapperService = new MapperService(indexSettings, analysisService, similarityService, mapperRegistry); - DocumentMapper.Builder b = new DocumentMapper.Builder(settings, rootBuilder, mapperService); - DocumentMapperParser parser = mapperService.documentMapperParser(); - this.docMapper = b.build(mapperService, parser); + DocumentMapper.Builder b = new DocumentMapper.Builder(rootBuilder, mapperService); + this.docMapper = b.build(mapperService); } @Override diff --git a/core/src/test/java/org/elasticsearch/index/mapper/DocumentFieldMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/DocumentFieldMapperTests.java new file mode 100644 index 00000000000..90976dac4b1 --- /dev/null +++ b/core/src/test/java/org/elasticsearch/index/mapper/DocumentFieldMapperTests.java @@ -0,0 +1,144 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.index.mapper; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.TokenStream; +import org.apache.lucene.analysis.Tokenizer; +import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; +import org.apache.lucene.document.Field; +import org.apache.lucene.util.LuceneTestCase; +import org.elasticsearch.Version; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.analysis.NamedAnalyzer; + +import java.io.IOException; +import java.io.StringReader; +import java.util.Arrays; +import java.util.List; + +public class DocumentFieldMapperTests extends LuceneTestCase { + + private static class FakeAnalyzer extends Analyzer { + + private final String output; + + public FakeAnalyzer(String output) { + this.output = output; + } + + @Override + protected TokenStreamComponents createComponents(String fieldName) { + Tokenizer tokenizer = new Tokenizer() { + boolean incremented = false; + CharTermAttribute term = addAttribute(CharTermAttribute.class); + + @Override + public boolean incrementToken() throws IOException { + if (incremented) { + return false; + } + term.setLength(0).append(output); + incremented = true; + return true; + } + }; + return new TokenStreamComponents(tokenizer); + } + + } + + static class FakeFieldType extends MappedFieldType { + + public FakeFieldType() { + super(); + } + + FakeFieldType(FakeFieldType other) { + super(other); + } + + @Override + public MappedFieldType clone() { + return new FakeFieldType(this); + } + + @Override + public String typeName() { + return "fake"; + } + + } + + static class FakeFieldMapper extends FieldMapper { + + private static final Settings SETTINGS = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build(); + + public FakeFieldMapper(String simpleName, MappedFieldType fieldType) { + super(simpleName, fieldType.clone(), fieldType.clone(), SETTINGS, null, null); + } + + @Override + protected void parseCreateField(ParseContext context, List fields) throws IOException { + } + + @Override + protected String contentType() { + return null; + } + + } + + public void testAnalyzers() throws IOException { + FakeFieldType fieldType1 = new FakeFieldType(); + fieldType1.setNames(new MappedFieldType.Names("field1")); + fieldType1.setIndexAnalyzer(new NamedAnalyzer("foo", new FakeAnalyzer("index"))); + fieldType1.setSearchAnalyzer(new NamedAnalyzer("bar", new FakeAnalyzer("search"))); + fieldType1.setSearchQuoteAnalyzer(new NamedAnalyzer("baz", new FakeAnalyzer("search_quote"))); + FieldMapper fieldMapper1 = new FakeFieldMapper("field1", fieldType1); + + FakeFieldType fieldType2 = new FakeFieldType(); + fieldType2.setNames(new MappedFieldType.Names("field2")); + FieldMapper fieldMapper2 = new FakeFieldMapper("field2", fieldType2); + + Analyzer defaultIndex = new FakeAnalyzer("default_index"); + Analyzer defaultSearch = new FakeAnalyzer("default_search"); + Analyzer defaultSearchQuote = new FakeAnalyzer("default_search_quote"); + + DocumentFieldMappers documentFieldMappers = new DocumentFieldMappers(Arrays.asList(fieldMapper1, fieldMapper2), defaultIndex, defaultSearch, defaultSearchQuote); + + assertAnalyzes(documentFieldMappers.indexAnalyzer(), "field1", "index"); + assertAnalyzes(documentFieldMappers.searchAnalyzer(), "field1", "search"); + assertAnalyzes(documentFieldMappers.searchQuoteAnalyzer(), "field1", "search_quote"); + + assertAnalyzes(documentFieldMappers.indexAnalyzer(), "field2", "default_index"); + assertAnalyzes(documentFieldMappers.searchAnalyzer(), "field2", "default_search"); + assertAnalyzes(documentFieldMappers.searchQuoteAnalyzer(), "field2", "default_search_quote"); + } + + private void assertAnalyzes(Analyzer analyzer, String field, String output) throws IOException { + try (TokenStream tok = analyzer.tokenStream(field, new StringReader(""))) { + CharTermAttribute term = tok.addAttribute(CharTermAttribute.class); + assertTrue(tok.incrementToken()); + assertEquals(output, term.toString()); + } + } +} diff --git a/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java b/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java index 5a31618f14e..8452c836041 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java @@ -31,6 +31,8 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import static org.hamcrest.Matchers.containsString; + public class FieldTypeLookupTests extends ESTestCase { public void testEmpty() { @@ -53,7 +55,7 @@ public class FieldTypeLookupTests extends ESTestCase { public void testDefaultMapping() { FieldTypeLookup lookup = new FieldTypeLookup(); try { - lookup.copyAndAddAll(MapperService.DEFAULT_MAPPING, Collections.emptyList()); + lookup.copyAndAddAll(MapperService.DEFAULT_MAPPING, Collections.emptyList(), randomBoolean()); fail(); } catch (IllegalArgumentException expected) { assertEquals("Default mappings should not be added to the lookup", expected.getMessage()); @@ -63,7 +65,7 @@ public class FieldTypeLookupTests extends ESTestCase { public void testAddNewField() { FieldTypeLookup lookup = new FieldTypeLookup(); FakeFieldMapper f = new FakeFieldMapper("foo", "bar"); - FieldTypeLookup lookup2 = lookup.copyAndAddAll("type", newList(f)); + FieldTypeLookup lookup2 = lookup.copyAndAddAll("type", newList(f), randomBoolean()); assertNull(lookup.get("foo")); assertNull(lookup.get("bar")); assertNull(lookup.getByIndexName("foo")); @@ -85,94 +87,77 @@ public class FieldTypeLookupTests extends ESTestCase { public void testAddExistingField() { FakeFieldMapper f = new FakeFieldMapper("foo", "foo"); - MappedFieldType originalFieldType = f.fieldType(); FakeFieldMapper f2 = new FakeFieldMapper("foo", "foo"); FieldTypeLookup lookup = new FieldTypeLookup(); - lookup = lookup.copyAndAddAll("type1", newList(f)); - FieldTypeLookup lookup2 = lookup.copyAndAddAll("type2", newList(f2)); + lookup = lookup.copyAndAddAll("type1", newList(f), randomBoolean()); + FieldTypeLookup lookup2 = lookup.copyAndAddAll("type2", newList(f2), randomBoolean()); - assertNotSame(originalFieldType, f.fieldType()); - assertSame(f.fieldType(), f2.fieldType()); - assertSame(f.fieldType(), lookup2.get("foo")); - assertSame(f.fieldType(), lookup2.getByIndexName("foo")); + assertSame(f2.fieldType(), lookup2.get("foo")); + assertSame(f2.fieldType(), lookup2.getByIndexName("foo")); assertEquals(1, size(lookup2.iterator())); } public void testAddExistingIndexName() { FakeFieldMapper f = new FakeFieldMapper("foo", "foo"); FakeFieldMapper f2 = new FakeFieldMapper("bar", "foo"); - MappedFieldType originalFieldType = f.fieldType(); FieldTypeLookup lookup = new FieldTypeLookup(); - lookup = lookup.copyAndAddAll("type1", newList(f)); - FieldTypeLookup lookup2 = lookup.copyAndAddAll("type2", newList(f2)); + lookup = lookup.copyAndAddAll("type1", newList(f), randomBoolean()); + FieldTypeLookup lookup2 = lookup.copyAndAddAll("type2", newList(f2), randomBoolean()); - assertNotSame(originalFieldType, f.fieldType()); - assertSame(f.fieldType(), f2.fieldType()); assertSame(f.fieldType(), lookup2.get("foo")); - assertSame(f.fieldType(), lookup2.get("bar")); - assertSame(f.fieldType(), lookup2.getByIndexName("foo")); + assertSame(f2.fieldType(), lookup2.get("bar")); + assertSame(f2.fieldType(), lookup2.getByIndexName("foo")); assertEquals(2, size(lookup2.iterator())); } public void testAddExistingFullName() { FakeFieldMapper f = new FakeFieldMapper("foo", "foo"); FakeFieldMapper f2 = new FakeFieldMapper("foo", "bar"); - MappedFieldType originalFieldType = f.fieldType(); FieldTypeLookup lookup = new FieldTypeLookup(); - lookup = lookup.copyAndAddAll("type1", newList(f)); - FieldTypeLookup lookup2 = lookup.copyAndAddAll("type2", newList(f2)); - - assertNotSame(originalFieldType, f.fieldType()); - assertSame(f.fieldType(), f2.fieldType()); - assertSame(f.fieldType(), lookup2.get("foo")); - assertSame(f.fieldType(), lookup2.getByIndexName("foo")); - assertSame(f.fieldType(), lookup2.getByIndexName("bar")); - assertEquals(1, size(lookup2.iterator())); + try { + lookup.copyAndAddAll("type2", newList(f2), randomBoolean()); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString("mapper [foo] has different [index_name]")); + } } public void testAddExistingBridgeName() { FakeFieldMapper f = new FakeFieldMapper("foo", "foo"); FakeFieldMapper f2 = new FakeFieldMapper("bar", "bar"); FieldTypeLookup lookup = new FieldTypeLookup(); - lookup = lookup.copyAndAddAll("type1", newList(f, f2)); + lookup = lookup.copyAndAddAll("type1", newList(f, f2), randomBoolean()); try { FakeFieldMapper f3 = new FakeFieldMapper("foo", "bar"); - lookup.copyAndAddAll("type2", newList(f3)); + lookup.copyAndAddAll("type2", newList(f3), randomBoolean()); } catch (IllegalStateException e) { assertTrue(e.getMessage().contains("insane mappings")); } try { FakeFieldMapper f3 = new FakeFieldMapper("bar", "foo"); - lookup.copyAndAddAll("type2", newList(f3)); + lookup.copyAndAddAll("type2", newList(f3), randomBoolean()); } catch (IllegalStateException e) { assertTrue(e.getMessage().contains("insane mappings")); } } - public void testCheckCompatibilityNewField() { - FakeFieldMapper f1 = new FakeFieldMapper("foo", "bar"); - FieldTypeLookup lookup = new FieldTypeLookup(); - lookup.checkCompatibility("type", newList(f1), false); - } - public void testCheckCompatibilityMismatchedTypes() { FieldMapper f1 = new FakeFieldMapper("foo", "bar"); FieldTypeLookup lookup = new FieldTypeLookup(); - lookup = lookup.copyAndAddAll("type", newList(f1)); + lookup = lookup.copyAndAddAll("type", newList(f1), randomBoolean()); MappedFieldType ft2 = FakeFieldMapper.makeOtherFieldType("foo", "foo"); FieldMapper f2 = new FakeFieldMapper("foo", ft2); try { - lookup.checkCompatibility("type2", newList(f2), false); + lookup.copyAndAddAll("type2", newList(f2), false); fail("expected type mismatch"); } catch (IllegalArgumentException e) { assertTrue(e.getMessage().contains("cannot be changed from type [faketype] to [otherfaketype]")); } // fails even if updateAllTypes == true try { - lookup.checkCompatibility("type2", newList(f2), true); + lookup.copyAndAddAll("type2", newList(f2), true); fail("expected type mismatch"); } catch (IllegalArgumentException e) { assertTrue(e.getMessage().contains("cannot be changed from type [faketype] to [otherfaketype]")); @@ -182,33 +167,33 @@ public class FieldTypeLookupTests extends ESTestCase { public void testCheckCompatibilityConflict() { FieldMapper f1 = new FakeFieldMapper("foo", "bar"); FieldTypeLookup lookup = new FieldTypeLookup(); - lookup = lookup.copyAndAddAll("type", newList(f1)); + lookup = lookup.copyAndAddAll("type", newList(f1), randomBoolean()); MappedFieldType ft2 = FakeFieldMapper.makeFieldType("foo", "bar"); ft2.setBoost(2.0f); FieldMapper f2 = new FakeFieldMapper("foo", ft2); try { // different type - lookup.checkCompatibility("type2", newList(f2), false); + lookup.copyAndAddAll("type2", newList(f2), false); fail("expected conflict"); } catch (IllegalArgumentException e) { assertTrue(e.getMessage().contains("to update [boost] across all types")); } - lookup.checkCompatibility("type", newList(f2), false); // boost is updateable, so ok since we are implicitly updating all types - lookup.checkCompatibility("type2", newList(f2), true); // boost is updateable, so ok if forcing + lookup.copyAndAddAll("type", newList(f2), false); // boost is updateable, so ok since we are implicitly updating all types + lookup.copyAndAddAll("type2", newList(f2), true); // boost is updateable, so ok if forcing // now with a non changeable setting MappedFieldType ft3 = FakeFieldMapper.makeFieldType("foo", "bar"); ft3.setStored(true); FieldMapper f3 = new FakeFieldMapper("foo", ft3); try { - lookup.checkCompatibility("type2", newList(f3), false); + lookup.copyAndAddAll("type2", newList(f3), false); fail("expected conflict"); } catch (IllegalArgumentException e) { assertTrue(e.getMessage().contains("has different [store] values")); } // even with updateAllTypes == true, incompatible try { - lookup.checkCompatibility("type2", newList(f3), true); + lookup.copyAndAddAll("type2", newList(f3), true); fail("expected conflict"); } catch (IllegalArgumentException e) { assertTrue(e.getMessage().contains("has different [store] values")); @@ -219,7 +204,7 @@ public class FieldTypeLookupTests extends ESTestCase { FakeFieldMapper f1 = new FakeFieldMapper("foo", "baz"); FakeFieldMapper f2 = new FakeFieldMapper("bar", "boo"); FieldTypeLookup lookup = new FieldTypeLookup(); - lookup = lookup.copyAndAddAll("type", newList(f1, f2)); + lookup = lookup.copyAndAddAll("type", newList(f1, f2), randomBoolean()); Collection names = lookup.simpleMatchToIndexNames("b*"); assertTrue(names.contains("baz")); assertTrue(names.contains("boo")); @@ -229,7 +214,7 @@ public class FieldTypeLookupTests extends ESTestCase { FakeFieldMapper f1 = new FakeFieldMapper("foo", "baz"); FakeFieldMapper f2 = new FakeFieldMapper("bar", "boo"); FieldTypeLookup lookup = new FieldTypeLookup(); - lookup = lookup.copyAndAddAll("type", newList(f1, f2)); + lookup = lookup.copyAndAddAll("type", newList(f1, f2), randomBoolean()); Collection names = lookup.simpleMatchToFullName("b*"); assertTrue(names.contains("foo")); assertTrue(names.contains("bar")); @@ -238,7 +223,7 @@ public class FieldTypeLookupTests extends ESTestCase { public void testIteratorImmutable() { FakeFieldMapper f1 = new FakeFieldMapper("foo", "bar"); FieldTypeLookup lookup = new FieldTypeLookup(); - lookup = lookup.copyAndAddAll("type", newList(f1)); + lookup = lookup.copyAndAddAll("type", newList(f1), randomBoolean()); try { Iterator itr = lookup.iterator(); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/camelcase/CamelCaseFieldNameTests.java b/core/src/test/java/org/elasticsearch/index/mapper/camelcase/CamelCaseFieldNameTests.java index 4fe0f9b77b4..ea142d6f441 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/camelcase/CamelCaseFieldNameTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/camelcase/CamelCaseFieldNameTests.java @@ -44,6 +44,7 @@ public class CamelCaseFieldNameTests extends ESSingleNodeTestCase { assertNotNull(doc.dynamicMappingsUpdate()); client().admin().indices().preparePutMapping("test").setType("type").setSource(doc.dynamicMappingsUpdate().toString()).get(); + documentMapper = index.mapperService().documentMapper("type"); assertNotNull(documentMapper.mappers().getMapper("thisIsCamelCase")); assertNull(documentMapper.mappers().getMapper("this_is_camel_case")); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/copyto/CopyToMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/copyto/CopyToMapperTests.java index 149d0be305f..daf54d501d7 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/copyto/CopyToMapperTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/copyto/CopyToMapperTests.java @@ -32,6 +32,7 @@ import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.DocumentMapperParser; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.MapperParsingException; +import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParseContext.Document; import org.elasticsearch.index.mapper.ParsedDocument; @@ -39,6 +40,7 @@ import org.elasticsearch.index.mapper.core.LongFieldMapper; import org.elasticsearch.index.mapper.core.StringFieldMapper; import org.elasticsearch.test.ESSingleNodeTestCase; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -127,6 +129,7 @@ public class CopyToMapperTests extends ESSingleNodeTestCase { assertNotNull(parsedDoc.dynamicMappingsUpdate()); client().admin().indices().preparePutMapping("test").setType("type1").setSource(parsedDoc.dynamicMappingsUpdate().toString()).get(); + docMapper = index.mapperService().documentMapper("type1"); fieldMapper = docMapper.mappers().getMapper("new_field"); assertThat(fieldMapper, instanceOf(LongFieldMapper.class)); } @@ -308,27 +311,15 @@ public class CopyToMapperTests extends ESSingleNodeTestCase { .endObject().endObject().endObject().string(); - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper docMapperBefore = parser.parse("type1", new CompressedXContent(mappingBefore)); + MapperService mapperService = createIndex("test").mapperService(); + DocumentMapper docMapperBefore = mapperService.merge("type1", new CompressedXContent(mappingBefore), true, false); - List fields = docMapperBefore.mappers().getMapper("copy_test").copyTo().copyToFields(); + assertEquals(Arrays.asList("foo", "bar"), docMapperBefore.mappers().getMapper("copy_test").copyTo().copyToFields()); - assertThat(fields.size(), equalTo(2)); - assertThat(fields.get(0), equalTo("foo")); - assertThat(fields.get(1), equalTo("bar")); + DocumentMapper docMapperAfter = mapperService.merge("type1", new CompressedXContent(mappingAfter), false, false); - - DocumentMapper docMapperAfter = parser.parse("type1", new CompressedXContent(mappingAfter)); - - docMapperBefore.merge(docMapperAfter.mapping(), true, false); - - docMapperBefore.merge(docMapperAfter.mapping(), false, false); - - fields = docMapperBefore.mappers().getMapper("copy_test").copyTo().copyToFields(); - - assertThat(fields.size(), equalTo(2)); - assertThat(fields.get(0), equalTo("baz")); - assertThat(fields.get(1), equalTo("bar")); + assertEquals(Arrays.asList("baz", "bar"), docMapperAfter.mappers().getMapper("copy_test").copyTo().copyToFields()); + assertEquals(Arrays.asList("foo", "bar"), docMapperBefore.mappers().getMapper("copy_test").copyTo().copyToFields()); } public void testCopyToNestedField() throws Exception { diff --git a/core/src/test/java/org/elasticsearch/index/mapper/core/TokenCountFieldMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/core/TokenCountFieldMapperTests.java index 25a9adf7125..a746717b73a 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/core/TokenCountFieldMapperTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/core/TokenCountFieldMapperTests.java @@ -28,6 +28,7 @@ import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.DocumentMapperParser; +import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.test.ESSingleNodeTestCase; import java.io.IOException; @@ -50,8 +51,8 @@ public class TokenCountFieldMapperTests extends ESSingleNodeTestCase { .endObject() .endObject() .endObject().endObject().string(); - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper stage1 = parser.parse("person", new CompressedXContent(stage1Mapping)); + MapperService mapperService = createIndex("test").mapperService(); + DocumentMapper stage1 = mapperService.merge("person", new CompressedXContent(stage1Mapping), true, false); String stage2Mapping = XContentFactory.jsonBuilder().startObject() .startObject("person") @@ -62,15 +63,12 @@ public class TokenCountFieldMapperTests extends ESSingleNodeTestCase { .endObject() .endObject() .endObject().endObject().string(); - DocumentMapper stage2 = parser.parse("person", new CompressedXContent(stage2Mapping)); + DocumentMapper stage2 = mapperService.merge("person", new CompressedXContent(stage2Mapping), false, false); - stage1.merge(stage2.mapping(), true, false); - // Just simulated so merge hasn't happened yet + // previous mapper has not been modified assertThat(((TokenCountFieldMapper) stage1.mappers().smartNameFieldMapper("tc")).analyzer(), equalTo("keyword")); - - stage1.merge(stage2.mapping(), false, false); - // Just simulated so merge hasn't happened yet - assertThat(((TokenCountFieldMapper) stage1.mappers().smartNameFieldMapper("tc")).analyzer(), equalTo("standard")); + // but the new one has the change + assertThat(((TokenCountFieldMapper) stage2.mappers().smartNameFieldMapper("tc")).analyzer(), equalTo("standard")); } public void testCountPositions() throws IOException { diff --git a/core/src/test/java/org/elasticsearch/index/mapper/date/SimpleDateMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/date/SimpleDateMappingTests.java index a4009c8a861..091c1ca2801 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/date/SimpleDateMappingTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/date/SimpleDateMappingTests.java @@ -80,7 +80,9 @@ public class SimpleDateMappingTests extends ESSingleNodeTestCase { .startObject("properties").endObject() .endObject().endObject().string(); - DocumentMapper defaultMapper = mapper("test", "type", mapping); + IndexService index = createIndex("test"); + client().admin().indices().preparePutMapping("test").setType("type").setSource(mapping).get(); + DocumentMapper defaultMapper = index.mapperService().documentMapper("type"); ParsedDocument doc = defaultMapper.parse("test", "type", "1", XContentFactory.jsonBuilder() .startObject() @@ -94,6 +96,7 @@ public class SimpleDateMappingTests extends ESSingleNodeTestCase { assertNotNull(doc.dynamicMappingsUpdate()); client().admin().indices().preparePutMapping("test").setType("type").setSource(doc.dynamicMappingsUpdate().toString()).get(); + defaultMapper = index.mapperService().documentMapper("type"); FieldMapper fieldMapper = defaultMapper.mappers().smartNameFieldMapper("date_field1"); assertThat(fieldMapper, instanceOf(DateFieldMapper.class)); DateFieldMapper dateFieldMapper = (DateFieldMapper)fieldMapper; @@ -384,7 +387,7 @@ public class SimpleDateMappingTests extends ESSingleNodeTestCase { Map config = getConfigurationViaXContent(initialDateFieldMapper); assertThat(config.get("format"), is("EEE MMM dd HH:mm:ss.S Z yyyy||EEE MMM dd HH:mm:ss.SSS Z yyyy")); - defaultMapper.merge(mergeMapper.mapping(), false, false); + defaultMapper = defaultMapper.merge(mergeMapper.mapping(), false); assertThat(defaultMapper.mappers().getMapper("field"), is(instanceOf(DateFieldMapper.class))); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/dynamictemplate/genericstore/GenericStoreDynamicTemplateTests.java b/core/src/test/java/org/elasticsearch/index/mapper/dynamictemplate/genericstore/GenericStoreDynamicTemplateTests.java index d07e6177814..da5c53f46f9 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/dynamictemplate/genericstore/GenericStoreDynamicTemplateTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/dynamictemplate/genericstore/GenericStoreDynamicTemplateTests.java @@ -44,6 +44,7 @@ public class GenericStoreDynamicTemplateTests extends ESSingleNodeTestCase { byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/dynamictemplate/genericstore/test-data.json"); ParsedDocument parsedDoc = docMapper.parse("test", "person", "1", new BytesArray(json)); client().admin().indices().preparePutMapping("test").setType("person").setSource(parsedDoc.dynamicMappingsUpdate().toString()).get(); + docMapper = index.mapperService().documentMapper("person"); Document doc = parsedDoc.rootDoc(); IndexableField f = doc.getField("name"); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/dynamictemplate/pathmatch/PathMatchDynamicTemplateTests.java b/core/src/test/java/org/elasticsearch/index/mapper/dynamictemplate/pathmatch/PathMatchDynamicTemplateTests.java index 829730e68cd..75dd396d8dd 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/dynamictemplate/pathmatch/PathMatchDynamicTemplateTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/dynamictemplate/pathmatch/PathMatchDynamicTemplateTests.java @@ -44,6 +44,7 @@ public class PathMatchDynamicTemplateTests extends ESSingleNodeTestCase { byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/dynamictemplate/pathmatch/test-data.json"); ParsedDocument parsedDoc = docMapper.parse("test", "person", "1", new BytesArray(json)); client().admin().indices().preparePutMapping("test").setType("person").setSource(parsedDoc.dynamicMappingsUpdate().toString()).get(); + docMapper = index.mapperService().documentMapper("person"); Document doc = parsedDoc.rootDoc(); IndexableField f = doc.getField("name"); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/dynamictemplate/simple/SimpleDynamicTemplatesTests.java b/core/src/test/java/org/elasticsearch/index/mapper/dynamictemplate/simple/SimpleDynamicTemplatesTests.java index 014f0295808..250b7a8d28a 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/dynamictemplate/simple/SimpleDynamicTemplatesTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/dynamictemplate/simple/SimpleDynamicTemplatesTests.java @@ -55,6 +55,7 @@ public class SimpleDynamicTemplatesTests extends ESSingleNodeTestCase { ParsedDocument parsedDoc = docMapper.parse("test", "person", "1", builder.bytes()); client().admin().indices().preparePutMapping("test").setType("person").setSource(parsedDoc.dynamicMappingsUpdate().toString()).get(); + docMapper = index.mapperService().documentMapper("person"); DocumentFieldMappers mappers = docMapper.mappers(); assertThat(mappers.smartNameFieldMapper("s"), Matchers.notNullValue()); @@ -74,6 +75,7 @@ public class SimpleDynamicTemplatesTests extends ESSingleNodeTestCase { byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/dynamictemplate/simple/test-data.json"); ParsedDocument parsedDoc = docMapper.parse("test", "person", "1", new BytesArray(json)); client().admin().indices().preparePutMapping("test").setType("person").setSource(parsedDoc.dynamicMappingsUpdate().toString()).get(); + docMapper = index.mapperService().documentMapper("person"); Document doc = parsedDoc.rootDoc(); IndexableField f = doc.getField("name"); @@ -130,6 +132,7 @@ public class SimpleDynamicTemplatesTests extends ESSingleNodeTestCase { byte[] json = copyToBytesFromClasspath("/org/elasticsearch/index/mapper/dynamictemplate/simple/test-data.json"); ParsedDocument parsedDoc = docMapper.parse("test", "person", "1", new BytesArray(json)); client().admin().indices().preparePutMapping("test").setType("person").setSource(parsedDoc.dynamicMappingsUpdate().toString()).get(); + docMapper = index.mapperService().documentMapper("person"); Document doc = parsedDoc.rootDoc(); IndexableField f = doc.getField("name"); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/externalvalues/ExternalMapper.java b/core/src/test/java/org/elasticsearch/index/mapper/externalvalues/ExternalMapper.java index dc6c720402e..c4b04000eb6 100755 --- a/core/src/test/java/org/elasticsearch/index/mapper/externalvalues/ExternalMapper.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/externalvalues/ExternalMapper.java @@ -35,6 +35,7 @@ import org.elasticsearch.index.mapper.MapperParsingException; import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.core.BinaryFieldMapper; import org.elasticsearch.index.mapper.core.BooleanFieldMapper; +import org.elasticsearch.index.mapper.core.StringFieldMapper; import org.elasticsearch.index.mapper.geo.BaseGeoPointFieldMapper; import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper; import org.elasticsearch.index.mapper.geo.GeoPointFieldMapperLegacy; @@ -160,11 +161,11 @@ public class ExternalMapper extends FieldMapper { private final String generatedValue; private final String mapperName; - private final BinaryFieldMapper binMapper; - private final BooleanFieldMapper boolMapper; - private final BaseGeoPointFieldMapper pointMapper; - private final GeoShapeFieldMapper shapeMapper; - private final FieldMapper stringMapper; + private BinaryFieldMapper binMapper; + private BooleanFieldMapper boolMapper; + private BaseGeoPointFieldMapper pointMapper; + private GeoShapeFieldMapper shapeMapper; + private FieldMapper stringMapper; public ExternalMapper(String simpleName, MappedFieldType fieldType, String generatedValue, String mapperName, @@ -216,6 +217,36 @@ public class ExternalMapper extends FieldMapper { // ignore this for now } + @Override + public FieldMapper updateFieldType(Map fullNameToFieldType) { + ExternalMapper update = (ExternalMapper) super.updateFieldType(fullNameToFieldType); + MultiFields multiFieldsUpdate = multiFields.updateFieldType(fullNameToFieldType); + BinaryFieldMapper binMapperUpdate = (BinaryFieldMapper) binMapper.updateFieldType(fullNameToFieldType); + BooleanFieldMapper boolMapperUpdate = (BooleanFieldMapper) boolMapper.updateFieldType(fullNameToFieldType); + GeoPointFieldMapper pointMapperUpdate = (GeoPointFieldMapper) pointMapper.updateFieldType(fullNameToFieldType); + GeoShapeFieldMapper shapeMapperUpdate = (GeoShapeFieldMapper) shapeMapper.updateFieldType(fullNameToFieldType); + StringFieldMapper stringMapperUpdate = (StringFieldMapper) stringMapper.updateFieldType(fullNameToFieldType); + if (update == this + && multiFieldsUpdate == multiFields + && binMapperUpdate == binMapper + && boolMapperUpdate == boolMapper + && pointMapperUpdate == pointMapper + && shapeMapperUpdate == shapeMapper + && stringMapperUpdate == stringMapper) { + return this; + } + if (update == this) { + update = (ExternalMapper) clone(); + } + update.multiFields = multiFieldsUpdate; + update.binMapper = binMapperUpdate; + update.boolMapper = boolMapperUpdate; + update.pointMapper = pointMapperUpdate; + update.shapeMapper = shapeMapperUpdate; + update.stringMapper = stringMapperUpdate; + return update; + } + @Override public Iterator iterator() { return Iterators.concat(super.iterator(), Arrays.asList(binMapper, boolMapper, pointMapper, shapeMapper, stringMapper).iterator()); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/externalvalues/ExternalMetadataMapper.java b/core/src/test/java/org/elasticsearch/index/mapper/externalvalues/ExternalMetadataMapper.java index 7797762606a..6ff0a428f79 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/externalvalues/ExternalMetadataMapper.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/externalvalues/ExternalMetadataMapper.java @@ -53,23 +53,11 @@ public class ExternalMetadataMapper extends MetadataFieldMapper { super(FIELD_NAME, FIELD_TYPE, FIELD_TYPE, indexSettings); } - @Override - public String name() { - return CONTENT_TYPE; - } - @Override protected void parseCreateField(ParseContext context, List fields) throws IOException { // handled in post parse } - @Override - public void doMerge(Mapper mergeWith, boolean updateAllTypes) { - if (!(mergeWith instanceof ExternalMetadataMapper)) { - throw new IllegalArgumentException("Trying to merge " + mergeWith + " with " + this); - } - } - @Override public Iterator iterator() { return Collections.emptyIterator(); @@ -97,7 +85,7 @@ public class ExternalMetadataMapper extends MetadataFieldMapper { public static class Builder extends MetadataFieldMapper.Builder { protected Builder() { - super(CONTENT_TYPE, FIELD_TYPE, FIELD_TYPE); + super(FIELD_NAME, FIELD_TYPE, FIELD_TYPE); } @Override diff --git a/core/src/test/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapperTests.java index 380a1e04ad3..76dba99e05b 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapperTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapperTests.java @@ -376,7 +376,7 @@ public class GeoShapeFieldMapperTests extends ESSingleNodeTestCase { .field("precision", "1m").field("tree_levels", 8).field("distance_error_pct", 0.01).field("orientation", "ccw") .endObject().endObject().endObject().endObject().string(); MapperService mapperService = createIndex("test").mapperService(); - DocumentMapper stage1 = mapperService.merge("type", new CompressedXContent(stage1Mapping), true, false); + DocumentMapper docMapper = mapperService.merge("type", new CompressedXContent(stage1Mapping), true, false); String stage2Mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("shape").field("type", "geo_shape").field("tree", "quadtree") .field("strategy", "term").field("precision", "1km").field("tree_levels", 26).field("distance_error_pct", 26) @@ -392,7 +392,7 @@ public class GeoShapeFieldMapperTests extends ESSingleNodeTestCase { } // verify nothing changed - FieldMapper fieldMapper = stage1.mappers().getMapper("shape"); + FieldMapper fieldMapper = docMapper.mappers().getMapper("shape"); assertThat(fieldMapper, instanceOf(GeoShapeFieldMapper.class)); GeoShapeFieldMapper geoShapeFieldMapper = (GeoShapeFieldMapper) fieldMapper; @@ -408,9 +408,9 @@ public class GeoShapeFieldMapperTests extends ESSingleNodeTestCase { stage2Mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("shape").field("type", "geo_shape").field("precision", "1m") .field("tree_levels", 8).field("distance_error_pct", 0.001).field("orientation", "cw").endObject().endObject().endObject().endObject().string(); - mapperService.merge("type", new CompressedXContent(stage2Mapping), false, false); + docMapper = mapperService.merge("type", new CompressedXContent(stage2Mapping), false, false); - fieldMapper = stage1.mappers().getMapper("shape"); + fieldMapper = docMapper.mappers().getMapper("shape"); assertThat(fieldMapper, instanceOf(GeoShapeFieldMapper.class)); geoShapeFieldMapper = (GeoShapeFieldMapper) fieldMapper; diff --git a/core/src/test/java/org/elasticsearch/index/mapper/index/IndexTypeMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/index/IndexTypeMapperTests.java index 70a714b29ec..d2065f439cb 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/index/IndexTypeMapperTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/index/IndexTypeMapperTests.java @@ -25,7 +25,7 @@ import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.mapper.DocumentMapper; -import org.elasticsearch.index.mapper.DocumentMapperParser; +import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.ParsedDocument; import org.elasticsearch.index.mapper.internal.IndexFieldMapper; import org.elasticsearch.test.ESSingleNodeTestCase; @@ -94,33 +94,16 @@ public class IndexTypeMapperTests extends ESSingleNodeTestCase { String mappingWithIndexEnabled = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_index").field("enabled", true).endObject() .endObject().endObject().string(); - DocumentMapperParser parser = createIndex("test", bwcSettings).mapperService().documentMapperParser(); - DocumentMapper mapperEnabled = parser.parse("type", new CompressedXContent(mappingWithIndexEnabled)); - + MapperService mapperService = createIndex("test", bwcSettings).mapperService(); + DocumentMapper mapperEnabled = mapperService.merge("type", new CompressedXContent(mappingWithIndexEnabled), true, false); + assertThat(mapperEnabled.IndexFieldMapper().enabled(), is(true)); String mappingWithIndexDisabled = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_index").field("enabled", false).endObject() .endObject().endObject().string(); - DocumentMapper mapperDisabled = parser.parse("type", new CompressedXContent(mappingWithIndexDisabled)); + DocumentMapper merged = mapperService.merge("type", new CompressedXContent(mappingWithIndexDisabled), false, false); - mapperEnabled.merge(mapperDisabled.mapping(), false, false); - assertThat(mapperEnabled.IndexFieldMapper().enabled(), is(false)); - } - - public void testThatDisablingWorksWhenMergingBackcompat() throws Exception { - String enabledMapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("_index").field("enabled", true).endObject() - .endObject().endObject().string(); - DocumentMapperParser parser = createIndex("test", bwcSettings).mapperService().documentMapperParser(); - DocumentMapper enabledMapper = parser.parse("type", new CompressedXContent(enabledMapping)); - - String disabledMapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("_index").field("enabled", false).endObject() - .endObject().endObject().string(); - DocumentMapper disabledMapper = parser.parse("type", new CompressedXContent(disabledMapping)); - - enabledMapper.merge(disabledMapper.mapping(), false, false); - assertThat(enabledMapper.indexMapper().enabled(), is(false)); + assertThat(merged.IndexFieldMapper().enabled(), is(false)); } public void testCustomSettingsBackcompat() throws Exception { diff --git a/core/src/test/java/org/elasticsearch/index/mapper/internal/FieldNamesFieldMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/internal/FieldNamesFieldMapperTests.java index d6c2cbf2e9f..e05bc21ba89 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/internal/FieldNamesFieldMapperTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/internal/FieldNamesFieldMapperTests.java @@ -187,15 +187,13 @@ public class FieldNamesFieldMapperTests extends ESSingleNodeTestCase { String disabledMapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_field_names").field("enabled", false).endObject() .endObject().endObject().string(); - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); + MapperService mapperService = createIndex("test").mapperService(); - DocumentMapper mapperEnabled = parser.parse("type", new CompressedXContent(enabledMapping)); - DocumentMapper mapperDisabled = parser.parse("type", new CompressedXContent(disabledMapping)); - mapperEnabled.merge(mapperDisabled.mapping(), false, false); - assertFalse(mapperEnabled.metadataMapper(FieldNamesFieldMapper.class).fieldType().isEnabled()); + DocumentMapper mapperEnabled = mapperService.merge("type", new CompressedXContent(enabledMapping), true, false); + DocumentMapper mapperDisabled = mapperService.merge("type", new CompressedXContent(disabledMapping), false, false); + assertFalse(mapperDisabled.metadataMapper(FieldNamesFieldMapper.class).fieldType().isEnabled()); - mapperEnabled = parser.parse("type", new CompressedXContent(enabledMapping)); - mapperDisabled.merge(mapperEnabled.mapping(), false, false); + mapperEnabled = mapperService.merge("type", new CompressedXContent(enabledMapping), false, false); assertTrue(mapperEnabled.metadataMapper(FieldNamesFieldMapper.class).fieldType().isEnabled()); } diff --git a/core/src/test/java/org/elasticsearch/index/mapper/lucene/DoubleIndexingDocTests.java b/core/src/test/java/org/elasticsearch/index/mapper/lucene/DoubleIndexingDocTests.java index 656599c5036..d171430dfff 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/lucene/DoubleIndexingDocTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/lucene/DoubleIndexingDocTests.java @@ -59,6 +59,7 @@ public class DoubleIndexingDocTests extends ESSingleNodeTestCase { .bytes()); assertNotNull(doc.dynamicMappingsUpdate()); client().admin().indices().preparePutMapping("test").setType("type").setSource(doc.dynamicMappingsUpdate().toString()).get(); + mapper = index.mapperService().documentMapper("type"); writer.addDocument(doc.rootDoc()); writer.addDocument(doc.rootDoc()); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/merge/TestMergeMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/merge/TestMergeMapperTests.java index d86a93e3f1b..80f7942bbcc 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/merge/TestMergeMapperTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/merge/TestMergeMapperTests.java @@ -59,15 +59,13 @@ public class TestMergeMapperTests extends ESSingleNodeTestCase { .endObject().endObject().endObject().string(); DocumentMapper stage2 = parser.parse("person", new CompressedXContent(stage2Mapping)); - stage1.merge(stage2.mapping(), true, false); - // since we are simulating, we should not have the age mapping + DocumentMapper merged = stage1.merge(stage2.mapping(), false); + // stage1 mapping should not have been modified assertThat(stage1.mappers().smartNameFieldMapper("age"), nullValue()); assertThat(stage1.mappers().smartNameFieldMapper("obj1.prop1"), nullValue()); - // now merge, don't simulate - stage1.merge(stage2.mapping(), false, false); - // but we have the age in - assertThat(stage1.mappers().smartNameFieldMapper("age"), notNullValue()); - assertThat(stage1.mappers().smartNameFieldMapper("obj1.prop1"), notNullValue()); + // but merged should + assertThat(merged.mappers().smartNameFieldMapper("age"), notNullValue()); + assertThat(merged.mappers().smartNameFieldMapper("obj1.prop1"), notNullValue()); } public void testMergeObjectDynamic() throws Exception { @@ -80,8 +78,8 @@ public class TestMergeMapperTests extends ESSingleNodeTestCase { DocumentMapper withDynamicMapper = parser.parse("type1", new CompressedXContent(withDynamicMapping)); assertThat(withDynamicMapper.root().dynamic(), equalTo(ObjectMapper.Dynamic.FALSE)); - mapper.merge(withDynamicMapper.mapping(), false, false); - assertThat(mapper.root().dynamic(), equalTo(ObjectMapper.Dynamic.FALSE)); + DocumentMapper merged = mapper.merge(withDynamicMapper.mapping(), false); + assertThat(merged.root().dynamic(), equalTo(ObjectMapper.Dynamic.FALSE)); } public void testMergeObjectAndNested() throws Exception { @@ -96,14 +94,14 @@ public class TestMergeMapperTests extends ESSingleNodeTestCase { DocumentMapper nestedMapper = parser.parse("type1", new CompressedXContent(nestedMapping)); try { - objectMapper.merge(nestedMapper.mapping(), true, false); + objectMapper.merge(nestedMapper.mapping(), false); fail(); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), containsString("object mapping [obj] can't be changed from non-nested to nested")); } try { - nestedMapper.merge(objectMapper.mapping(), true, false); + nestedMapper.merge(objectMapper.mapping(), false); fail(); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), containsString("object mapping [obj] can't be changed from nested to non-nested")); @@ -123,13 +121,13 @@ public class TestMergeMapperTests extends ESSingleNodeTestCase { DocumentMapper changed = parser.parse("type", new CompressedXContent(mapping2)); assertThat(((NamedAnalyzer) existing.mappers().getMapper("field").fieldType().searchAnalyzer()).name(), equalTo("whitespace")); - existing.merge(changed.mapping(), false, false); + DocumentMapper merged = existing.merge(changed.mapping(), false); - assertThat(((NamedAnalyzer) existing.mappers().getMapper("field").fieldType().searchAnalyzer()).name(), equalTo("keyword")); + assertThat(((NamedAnalyzer) merged.mappers().getMapper("field").fieldType().searchAnalyzer()).name(), equalTo("keyword")); } public void testChangeSearchAnalyzerToDefault() throws Exception { - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); + MapperService mapperService = createIndex("test").mapperService(); String mapping1 = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("field").field("type", "string").field("analyzer", "standard").field("search_analyzer", "whitespace").endObject().endObject() .endObject().endObject().string(); @@ -137,14 +135,13 @@ public class TestMergeMapperTests extends ESSingleNodeTestCase { .startObject("properties").startObject("field").field("type", "string").field("analyzer", "standard").field("ignore_above", 14).endObject().endObject() .endObject().endObject().string(); - DocumentMapper existing = parser.parse("type", new CompressedXContent(mapping1)); - DocumentMapper changed = parser.parse("type", new CompressedXContent(mapping2)); + DocumentMapper existing = mapperService.merge("type", new CompressedXContent(mapping1), true, false); + DocumentMapper merged = mapperService.merge("type", new CompressedXContent(mapping2), false, false); assertThat(((NamedAnalyzer) existing.mappers().getMapper("field").fieldType().searchAnalyzer()).name(), equalTo("whitespace")); - existing.merge(changed.mapping(), false, false); - assertThat(((NamedAnalyzer) existing.mappers().getMapper("field").fieldType().searchAnalyzer()).name(), equalTo("standard")); - assertThat(((StringFieldMapper) (existing.mappers().getMapper("field"))).getIgnoreAbove(), equalTo(14)); + assertThat(((NamedAnalyzer) merged.mappers().getMapper("field").fieldType().searchAnalyzer()).name(), equalTo("standard")); + assertThat(((StringFieldMapper) (merged.mappers().getMapper("field"))).getIgnoreAbove(), equalTo(14)); } public void testConcurrentMergeTest() throws Throwable { diff --git a/core/src/test/java/org/elasticsearch/index/mapper/multifield/MultiFieldTests.java b/core/src/test/java/org/elasticsearch/index/mapper/multifield/MultiFieldTests.java index 8a66a78f3ac..3c301e93fa5 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/multifield/MultiFieldTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/multifield/MultiFieldTests.java @@ -150,19 +150,17 @@ public class MultiFieldTests extends ESSingleNodeTestCase { public void testBuildThenParse() throws Exception { IndexService indexService = createIndex("test"); - Settings settings = indexService.getIndexSettings().getSettings(); - DocumentMapperParser mapperParser = indexService.mapperService().documentMapperParser(); - DocumentMapper builderDocMapper = doc(settings, rootObject("person").add( + DocumentMapper builderDocMapper = doc(rootObject("person").add( stringField("name").store(true) .addMultiField(stringField("indexed").index(true).tokenized(true)) .addMultiField(stringField("not_indexed").index(false).store(true)) - ), indexService.mapperService()).build(indexService.mapperService(), mapperParser); + ), indexService.mapperService()).build(indexService.mapperService()); String builtMapping = builderDocMapper.mappingSource().string(); // System.out.println(builtMapping); // reparse it - DocumentMapper docMapper = mapperParser.parse("person", new CompressedXContent(builtMapping)); + DocumentMapper docMapper = indexService.mapperService().documentMapperParser().parse("person", new CompressedXContent(builtMapping)); BytesReference json = new BytesArray(copyToBytesFromClasspath("/org/elasticsearch/index/mapper/multifield/test-data.json")); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/multifield/merge/JavaMultiFieldMergeTests.java b/core/src/test/java/org/elasticsearch/index/mapper/multifield/merge/JavaMultiFieldMergeTests.java index 1a999a64018..651b8c45d55 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/multifield/merge/JavaMultiFieldMergeTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/multifield/merge/JavaMultiFieldMergeTests.java @@ -25,7 +25,6 @@ import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.mapper.DocumentMapper; -import org.elasticsearch.index.mapper.DocumentMapperParser; import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.ParseContext.Document; import org.elasticsearch.test.ESSingleNodeTestCase; @@ -41,9 +40,9 @@ import static org.hamcrest.Matchers.nullValue; public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase { public void testMergeMultiField() throws Exception { String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping1.json"); - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); + MapperService mapperService = createIndex("test").mapperService(); - DocumentMapper docMapper = parser.parse("person", new CompressedXContent(mapping)); + DocumentMapper docMapper = mapperService.merge("person", new CompressedXContent(mapping), true, false); assertNotSame(IndexOptions.NONE, docMapper.mappers().getMapper("name").fieldType().indexOptions()); assertThat(docMapper.mappers().getMapper("name.indexed"), nullValue()); @@ -56,11 +55,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase { assertThat(f, nullValue()); mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping2.json"); - DocumentMapper docMapper2 = parser.parse("person", new CompressedXContent(mapping)); - - docMapper.merge(docMapper2.mapping(), true, false); - - docMapper.merge(docMapper2.mapping(), false, false); + docMapper = mapperService.merge("person", new CompressedXContent(mapping), false, false); assertNotSame(IndexOptions.NONE, docMapper.mappers().getMapper("name").fieldType().indexOptions()); @@ -77,11 +72,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase { assertThat(f, notNullValue()); mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping3.json"); - DocumentMapper docMapper3 = parser.parse("person", new CompressedXContent(mapping)); - - docMapper.merge(docMapper3.mapping(), true, false); - - docMapper.merge(docMapper3.mapping(), false, false); + docMapper = mapperService.merge("person", new CompressedXContent(mapping), false, false); assertNotSame(IndexOptions.NONE, docMapper.mappers().getMapper("name").fieldType().indexOptions()); @@ -92,11 +83,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase { assertThat(docMapper.mappers().getMapper("name.not_indexed3"), nullValue()); mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping4.json"); - DocumentMapper docMapper4 = parser.parse("person", new CompressedXContent(mapping)); - - docMapper.merge(docMapper4.mapping(), true, false); - - docMapper.merge(docMapper4.mapping(), false, false); + docMapper = mapperService.merge("person", new CompressedXContent(mapping), false, false); assertNotSame(IndexOptions.NONE, docMapper.mappers().getMapper("name").fieldType().indexOptions()); @@ -125,7 +112,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase { mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/upgrade1.json"); - mapperService.merge("person", new CompressedXContent(mapping), false, false); + docMapper = mapperService.merge("person", new CompressedXContent(mapping), false, false); assertNotSame(IndexOptions.NONE, docMapper.mappers().getMapper("name").fieldType().indexOptions()); @@ -142,7 +129,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase { assertThat(f, notNullValue()); mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/upgrade2.json"); - mapperService.merge("person", new CompressedXContent(mapping), false, false); + docMapper = mapperService.merge("person", new CompressedXContent(mapping), false, false); assertNotSame(IndexOptions.NONE, docMapper.mappers().getMapper("name").fieldType().indexOptions()); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/numeric/SimpleNumericTests.java b/core/src/test/java/org/elasticsearch/index/mapper/numeric/SimpleNumericTests.java index 14b6e7c7110..624978bf7d0 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/numeric/SimpleNumericTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/numeric/SimpleNumericTests.java @@ -74,6 +74,7 @@ public class SimpleNumericTests extends ESSingleNodeTestCase { assertNotNull(doc.dynamicMappingsUpdate()); client().admin().indices().preparePutMapping("test").setType("type").setSource(doc.dynamicMappingsUpdate().toString()).get(); + defaultMapper = index.mapperService().documentMapper("type"); FieldMapper mapper = defaultMapper.mappers().smartNameFieldMapper("s_long"); assertThat(mapper, instanceOf(LongFieldMapper.class)); @@ -98,6 +99,7 @@ public class SimpleNumericTests extends ESSingleNodeTestCase { assertNotNull(doc.dynamicMappingsUpdate()); assertAcked(client().admin().indices().preparePutMapping("test").setType("type").setSource(doc.dynamicMappingsUpdate().toString()).get()); + defaultMapper = index.mapperService().documentMapper("type"); FieldMapper mapper = defaultMapper.mappers().smartNameFieldMapper("s_long"); assertThat(mapper, instanceOf(StringFieldMapper.class)); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/simple/SimpleMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/simple/SimpleMapperTests.java index b04d3a64a25..230af8d3a50 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/simple/SimpleMapperTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/simple/SimpleMapperTests.java @@ -22,7 +22,6 @@ package org.elasticsearch.index.mapper.simple; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.compress.CompressedXContent; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.IndexService; import org.elasticsearch.index.mapper.DocumentMapper; @@ -48,12 +47,10 @@ import static org.hamcrest.Matchers.equalTo; public class SimpleMapperTests extends ESSingleNodeTestCase { public void testSimpleMapper() throws Exception { IndexService indexService = createIndex("test"); - Settings settings = indexService.getIndexSettings().getSettings(); - DocumentMapperParser mapperParser = indexService.mapperService().documentMapperParser(); - DocumentMapper docMapper = doc(settings, + DocumentMapper docMapper = doc( rootObject("person") .add(object("name").add(stringField("first").store(true).index(false))), - indexService.mapperService()).build(indexService.mapperService(), mapperParser); + indexService.mapperService()).build(indexService.mapperService()); BytesReference json = new BytesArray(copyToBytesFromClasspath("/org/elasticsearch/index/mapper/simple/test1.json")); Document doc = docMapper.parse("test", "person", "1", json).rootDoc(); @@ -110,12 +107,10 @@ public class SimpleMapperTests extends ESSingleNodeTestCase { public void testNoDocumentSent() throws Exception { IndexService indexService = createIndex("test"); - Settings settings = indexService.getIndexSettings().getSettings(); - DocumentMapperParser mapperParser = indexService.mapperService().documentMapperParser(); - DocumentMapper docMapper = doc(settings, + DocumentMapper docMapper = doc( rootObject("person") .add(object("name").add(stringField("first").store(true).index(false))), - indexService.mapperService()).build(indexService.mapperService(), mapperParser); + indexService.mapperService()).build(indexService.mapperService()); BytesReference json = new BytesArray("".getBytes(StandardCharsets.UTF_8)); try { diff --git a/core/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java index ea97aa6b8cf..35b127b6283 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java @@ -196,10 +196,10 @@ public class DefaultSourceMappingTests extends ESSingleNodeTestCase { DocumentMapper docMapper = parser.parse("type", new CompressedXContent(mapping1)); docMapper = parser.parse("type", docMapper.mappingSource()); if (conflicts.length == 0) { - docMapper.merge(parser.parse("type", new CompressedXContent(mapping2)).mapping(), true, false); + docMapper.merge(parser.parse("type", new CompressedXContent(mapping2)).mapping(), false); } else { try { - docMapper.merge(parser.parse("type", new CompressedXContent(mapping2)).mapping(), true, false); + docMapper.merge(parser.parse("type", new CompressedXContent(mapping2)).mapping(), false); fail(); } catch (IllegalArgumentException e) { for (String conflict : conflicts) { diff --git a/core/src/test/java/org/elasticsearch/index/mapper/string/SimpleStringMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/string/SimpleStringMappingTests.java index aac4b81aff2..218fc442224 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/string/SimpleStringMappingTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/string/SimpleStringMappingTests.java @@ -40,6 +40,7 @@ import org.elasticsearch.index.mapper.DocumentMapperParser; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.Mapper.BuilderContext; import org.elasticsearch.index.mapper.MapperParsingException; +import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.ParseContext.Document; import org.elasticsearch.index.mapper.ParsedDocument; import org.elasticsearch.index.mapper.core.StringFieldMapper; @@ -478,7 +479,8 @@ public class SimpleStringMappingTests extends ESSingleNodeTestCase { .startObject("properties").startObject("field").field("type", "string").endObject().endObject() .endObject().endObject().string(); - DocumentMapper defaultMapper = indexService.mapperService().merge("type", new CompressedXContent(mapping), true, false); + MapperService mapperService = indexService.mapperService(); + DocumentMapper defaultMapper = mapperService.merge("type", new CompressedXContent(mapping), true, false); ParsedDocument doc = defaultMapper.parse("test", "type", "1", XContentFactory.jsonBuilder() .startObject() @@ -492,7 +494,7 @@ public class SimpleStringMappingTests extends ESSingleNodeTestCase { String updatedMapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("field").field("type", "string").startObject("norms").field("enabled", false).endObject() .endObject().endObject().endObject().endObject().string(); - defaultMapper.merge(parser.parse("type", new CompressedXContent(updatedMapping)).mapping(), false, false); + defaultMapper = mapperService.merge("type", new CompressedXContent(updatedMapping), false, false); doc = defaultMapper.parse("test", "type", "1", XContentFactory.jsonBuilder() .startObject() @@ -507,7 +509,7 @@ public class SimpleStringMappingTests extends ESSingleNodeTestCase { .startObject("properties").startObject("field").field("type", "string").startObject("norms").field("enabled", true).endObject() .endObject().endObject().endObject().endObject().string(); try { - defaultMapper.merge(parser.parse("type", new CompressedXContent(updatedMapping)).mapping(), true, false); + mapperService.merge("type", new CompressedXContent(updatedMapping), false, false); fail(); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), containsString("different [omit_norms]")); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java index 01d4c6a1234..c6a8a2fca44 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java @@ -143,17 +143,16 @@ public class TimestampMappingTests extends ESSingleNodeTestCase { String enabledMapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_timestamp").field("enabled", true).endObject() .endObject().endObject().string(); - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper enabledMapper = parser.parse("type", new CompressedXContent(enabledMapping)); + MapperService mapperService = createIndex("test").mapperService(); + DocumentMapper enabledMapper = mapperService.merge("type", new CompressedXContent(enabledMapping), true, false); String disabledMapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_timestamp").field("enabled", false).endObject() .endObject().endObject().string(); - DocumentMapper disabledMapper = parser.parse("type", new CompressedXContent(disabledMapping)); + DocumentMapper disabledMapper = mapperService.merge("type", new CompressedXContent(disabledMapping), false, false); - enabledMapper.merge(disabledMapper.mapping(), false, false); - - assertThat(enabledMapper.timestampFieldMapper().enabled(), is(false)); + assertThat(enabledMapper.timestampFieldMapper().enabled(), is(true)); + assertThat(disabledMapper.timestampFieldMapper().enabled(), is(false)); } // issue 3174 @@ -504,16 +503,16 @@ public class TimestampMappingTests extends ESSingleNodeTestCase { .startObject("_timestamp").field("enabled", randomBoolean()).startObject("fielddata").field("loading", "lazy").field("format", "doc_values").endObject().field("store", "yes").endObject() .endObject().endObject().string(); Settings indexSettings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id).build(); - DocumentMapperParser parser = createIndex("test", indexSettings).mapperService().documentMapperParser(); + MapperService mapperService = createIndex("test", indexSettings).mapperService(); - DocumentMapper docMapper = parser.parse("type", new CompressedXContent(mapping)); + DocumentMapper docMapper = mapperService.merge("type", new CompressedXContent(mapping), true, false); assertThat(docMapper.timestampFieldMapper().fieldType().fieldDataType().getLoading(), equalTo(MappedFieldType.Loading.LAZY)); assertThat(docMapper.timestampFieldMapper().fieldType().fieldDataType().getFormat(indexSettings), equalTo("doc_values")); mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_timestamp").field("enabled", randomBoolean()).startObject("fielddata").field("loading", "eager").field("format", "array").endObject().field("store", "yes").endObject() .endObject().endObject().string(); - docMapper.merge(parser.parse("type", new CompressedXContent(mapping)).mapping(), false, false); + docMapper = mapperService.merge("type", new CompressedXContent(mapping), false, false); assertThat(docMapper.timestampFieldMapper().fieldType().fieldDataType().getLoading(), equalTo(MappedFieldType.Loading.EAGER)); assertThat(docMapper.timestampFieldMapper().fieldType().fieldDataType().getFormat(indexSettings), equalTo("array")); } @@ -571,8 +570,8 @@ public class TimestampMappingTests extends ESSingleNodeTestCase { .startObject("fielddata").field("format", "array").endObject() .field("store", "no") .field("index", "no") - .field("path", "bar") - .field("default", "1970-01-02") + .field("path", "foo") + .field("default", "1970-01-01") .endObject() .endObject().endObject().string(); @@ -584,6 +583,24 @@ public class TimestampMappingTests extends ESSingleNodeTestCase { assertThat(e.getMessage(), containsString("mapper [_timestamp] has different [store] values")); } + mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_timestamp").field("enabled", false) + .startObject("fielddata").field("format", "array").endObject() + .field("store", "yes") + .field("index", "analyzed") + .field("path", "bar") + .field("default", "1970-01-02") + .endObject() + .endObject().endObject().string(); + + try { + mapperService.merge("type", new CompressedXContent(mapping), false, false); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString("Cannot update default in _timestamp value")); + assertThat(e.getMessage(), containsString("Cannot update path in _timestamp value")); + } + assertThat(docMapper.timestampFieldMapper().fieldType().fieldDataType().getLoading(), equalTo(MappedFieldType.Loading.LAZY)); assertTrue(docMapper.timestampFieldMapper().enabled()); @@ -650,7 +667,7 @@ public class TimestampMappingTests extends ESSingleNodeTestCase { public void testBackcompatMergePaths() throws Exception { String[] possiblePathValues = {"some_path", "anotherPath", null}; - DocumentMapperParser parser = createIndex("test", BWC_SETTINGS).mapperService().documentMapperParser(); + MapperService mapperService = createIndex("test", BWC_SETTINGS).mapperService(); XContentBuilder mapping1 = XContentFactory.jsonBuilder().startObject() .startObject("type") .startObject("_timestamp"); @@ -670,21 +687,17 @@ public class TimestampMappingTests extends ESSingleNodeTestCase { mapping2.endObject() .endObject().endObject(); - assertConflict(mapping1.string(), mapping2.string(), parser, (path1 == path2 ? null : "Cannot update path in _timestamp value")); + assertConflict(mapperService, "type", mapping1.string(), mapping2.string(), (path1 == path2 ? null : "Cannot update path in _timestamp value")); } - void assertConflict(String mapping1, String mapping2, DocumentMapperParser parser, String conflict) throws IOException { - DocumentMapper docMapper = parser.parse("type", new CompressedXContent(mapping1)); - docMapper = parser.parse("type", docMapper.mappingSource()); - if (conflict == null) { - docMapper.merge(parser.parse("type", new CompressedXContent(mapping2)).mapping(), true, false); - } else { - try { - docMapper.merge(parser.parse("type", new CompressedXContent(mapping2)).mapping(), true, false); - fail(); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), containsString(conflict)); - } + void assertConflict(MapperService mapperService, String type, String mapping1, String mapping2, String conflict) throws IOException { + mapperService.merge("type", new CompressedXContent(mapping1), true, false); + try { + mapperService.merge("type", new CompressedXContent(mapping2), false, false); + assertNull(conflict); + } catch (IllegalArgumentException e) { + assertNotNull(conflict); + assertThat(e.getMessage(), containsString(conflict)); } } diff --git a/core/src/test/java/org/elasticsearch/index/mapper/ttl/TTLMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/ttl/TTLMappingTests.java index c43a7f1ddc5..10eeecf6749 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/ttl/TTLMappingTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/ttl/TTLMappingTests.java @@ -33,8 +33,8 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.IndexService; import org.elasticsearch.index.mapper.DocumentMapper; -import org.elasticsearch.index.mapper.DocumentMapperParser; import org.elasticsearch.index.mapper.MapperParsingException; +import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.ParsedDocument; import org.elasticsearch.index.mapper.SourceToParse; import org.elasticsearch.index.mapper.internal.TTLFieldMapper; @@ -111,13 +111,12 @@ public class TTLMappingTests extends ESSingleNodeTestCase { .startObject("properties").field("field").startObject().field("type", "string").endObject().endObject() .endObject().endObject().string(); - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper mapperWithoutTtl = parser.parse("type", new CompressedXContent(mappingWithoutTtl)); - DocumentMapper mapperWithTtl = parser.parse("type", new CompressedXContent(mappingWithTtl)); + MapperService mapperService = createIndex("test").mapperService(); + DocumentMapper mapperWithoutTtl = mapperService.merge("type", new CompressedXContent(mappingWithoutTtl), true, false); + DocumentMapper mapperWithTtl = mapperService.merge("type", new CompressedXContent(mappingWithTtl), false, false); - mapperWithoutTtl.merge(mapperWithTtl.mapping(), false, false); - - assertThat(mapperWithoutTtl.TTLFieldMapper().enabled(), equalTo(true)); + assertThat(mapperWithoutTtl.TTLFieldMapper().enabled(), equalTo(false)); + assertThat(mapperWithTtl.TTLFieldMapper().enabled(), equalTo(true)); } public void testThatChangingTTLKeepsMapperEnabled() throws Exception { @@ -135,24 +134,22 @@ public class TTLMappingTests extends ESSingleNodeTestCase { .startObject("properties").field("field").startObject().field("type", "string").endObject().endObject() .endObject().endObject().string(); - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper initialMapper = parser.parse("type", new CompressedXContent(mappingWithTtl)); - DocumentMapper updatedMapper = parser.parse("type", new CompressedXContent(updatedMapping)); - - initialMapper.merge(updatedMapper.mapping(), true, false); + MapperService mapperService = createIndex("test").mapperService(); + DocumentMapper initialMapper = mapperService.merge("type", new CompressedXContent(mappingWithTtl), true, false); + DocumentMapper updatedMapper = mapperService.merge("type", new CompressedXContent(updatedMapping), false, false); assertThat(initialMapper.TTLFieldMapper().enabled(), equalTo(true)); + assertThat(updatedMapper.TTLFieldMapper().enabled(), equalTo(true)); } public void testThatDisablingTTLReportsConflict() throws Exception { String mappingWithTtl = getMappingWithTtlEnabled().string(); String mappingWithTtlDisabled = getMappingWithTtlDisabled().string(); - DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); - DocumentMapper initialMapper = parser.parse("type", new CompressedXContent(mappingWithTtl)); - DocumentMapper updatedMapper = parser.parse("type", new CompressedXContent(mappingWithTtlDisabled)); + MapperService mapperService = createIndex("test").mapperService(); + DocumentMapper initialMapper = mapperService.merge("type", new CompressedXContent(mappingWithTtl), true, false); try { - initialMapper.merge(updatedMapper.mapping(), true, false); + mapperService.merge("type", new CompressedXContent(mappingWithTtlDisabled), false, false); fail(); } catch (IllegalArgumentException e) { // expected @@ -190,20 +187,20 @@ public class TTLMappingTests extends ESSingleNodeTestCase { public void testNoConflictIfNothingSetAndDisabledLater() throws Exception { IndexService indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type"); XContentBuilder mappingWithTtlDisabled = getMappingWithTtlDisabled("7d"); - indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlDisabled.string()), true).mapping(), randomBoolean(), false); + indexService.mapperService().merge("type", new CompressedXContent(mappingWithTtlDisabled.string()), randomBoolean(), false); } public void testNoConflictIfNothingSetAndEnabledLater() throws Exception { IndexService indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type"); XContentBuilder mappingWithTtlEnabled = getMappingWithTtlEnabled("7d"); - indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), randomBoolean(), false); + indexService.mapperService().merge("type", new CompressedXContent(mappingWithTtlEnabled.string()), randomBoolean(), false); } public void testMergeWithOnlyDefaultSet() throws Exception { XContentBuilder mappingWithTtlEnabled = getMappingWithTtlEnabled("7d"); IndexService indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type", mappingWithTtlEnabled); XContentBuilder mappingWithOnlyDefaultSet = getMappingWithOnlyTtlDefaultSet("6m"); - indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithOnlyDefaultSet.string()), true).mapping(), false, false); + indexService.mapperService().merge("type", new CompressedXContent(mappingWithOnlyDefaultSet.string()), false, false); CompressedXContent mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); assertThat(mappingAfterMerge, equalTo(new CompressedXContent("{\"type\":{\"_ttl\":{\"enabled\":true,\"default\":360000},\"properties\":{\"field\":{\"type\":\"string\"}}}}"))); } @@ -214,65 +211,11 @@ public class TTLMappingTests extends ESSingleNodeTestCase { CompressedXContent mappingAfterCreation = indexService.mapperService().documentMapper("type").mappingSource(); assertThat(mappingAfterCreation, equalTo(new CompressedXContent("{\"type\":{\"_ttl\":{\"enabled\":false},\"properties\":{\"field\":{\"type\":\"string\"}}}}"))); XContentBuilder mappingWithOnlyDefaultSet = getMappingWithOnlyTtlDefaultSet("6m"); - indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithOnlyDefaultSet.string()), true).mapping(), false, false); + indexService.mapperService().merge("type", new CompressedXContent(mappingWithOnlyDefaultSet.string()), false, false); CompressedXContent mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); assertThat(mappingAfterMerge, equalTo(new CompressedXContent("{\"type\":{\"_ttl\":{\"enabled\":false},\"properties\":{\"field\":{\"type\":\"string\"}}}}"))); } - public void testThatSimulatedMergingLeavesStateUntouched() throws Exception { - //check if default ttl changed when simulate set to true - XContentBuilder mappingWithTtl = getMappingWithTtlEnabled("6d"); - IndexService indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type", mappingWithTtl); - CompressedXContent mappingBeforeMerge = indexService.mapperService().documentMapper("type").mappingSource(); - XContentBuilder mappingWithTtlDifferentDefault = getMappingWithTtlEnabled("7d"); - indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlDifferentDefault.string()), true).mapping(), true, false); - // make sure simulate flag actually worked - no mappings applied - CompressedXContent mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); - assertThat(mappingAfterMerge, equalTo(mappingBeforeMerge)); - - client().admin().indices().prepareDelete("testindex").get(); - // check if enabled changed when simulate set to true - XContentBuilder mappingWithoutTtl = getMappingWithTtlDisabled(); - indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type", mappingWithoutTtl); - mappingBeforeMerge = indexService.mapperService().documentMapper("type").mappingSource(); - XContentBuilder mappingWithTtlEnabled = getMappingWithTtlEnabled(); - indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), true, false); - // make sure simulate flag actually worked - no mappings applied - mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); - assertThat(mappingAfterMerge, equalTo(mappingBeforeMerge)); - - client().admin().indices().prepareDelete("testindex").get(); - // check if enabled changed when simulate set to true - mappingWithoutTtl = getMappingWithTtlDisabled("6d"); - indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type", mappingWithoutTtl); - mappingBeforeMerge = indexService.mapperService().documentMapper("type").mappingSource(); - mappingWithTtlEnabled = getMappingWithTtlEnabled("7d"); - indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), true, false); - // make sure simulate flag actually worked - no mappings applied - mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); - assertThat(mappingAfterMerge, equalTo(mappingBeforeMerge)); - - client().admin().indices().prepareDelete("testindex").get(); - // check if switching simulate flag off works - mappingWithoutTtl = getMappingWithTtlDisabled("6d"); - indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type", mappingWithoutTtl); - mappingWithTtlEnabled = getMappingWithTtlEnabled("7d"); - indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), false, false); - // make sure simulate flag actually worked - mappings applied - mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); - assertThat(mappingAfterMerge, equalTo(new CompressedXContent("{\"type\":{\"_ttl\":{\"enabled\":true,\"default\":604800000},\"properties\":{\"field\":{\"type\":\"string\"}}}}"))); - - client().admin().indices().prepareDelete("testindex").get(); - // check if switching simulate flag off works if nothing was applied in the beginning - indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type"); - mappingWithTtlEnabled = getMappingWithTtlEnabled("7d"); - indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), false, false); - // make sure simulate flag actually worked - mappings applied - mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); - assertThat(mappingAfterMerge, equalTo(new CompressedXContent("{\"type\":{\"_ttl\":{\"enabled\":true,\"default\":604800000},\"properties\":{\"field\":{\"type\":\"string\"}}}}"))); - - } - public void testIncludeInObjectBackcompat() throws Exception { String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_ttl").field("enabled", true).endObject() diff --git a/core/src/test/java/org/elasticsearch/index/mapper/update/UpdateMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/update/UpdateMappingTests.java index f73ad3e3b3f..9510c6749eb 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/update/UpdateMappingTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/update/UpdateMappingTests.java @@ -76,7 +76,7 @@ public class UpdateMappingTests extends ESSingleNodeTestCase { private void testNoConflictWhileMergingAndMappingChanged(XContentBuilder mapping, XContentBuilder mappingUpdate, XContentBuilder expectedMapping) throws IOException { IndexService indexService = createIndex("test", Settings.settingsBuilder().build(), "type", mapping); // simulate like in MetaDataMappingService#putMapping - indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingUpdate.bytes()), true).mapping(), false, false); + indexService.mapperService().merge("type", new CompressedXContent(mappingUpdate.bytes()), false, false); // make sure mappings applied CompressedXContent mappingAfterUpdate = indexService.mapperService().documentMapper("type").mappingSource(); assertThat(mappingAfterUpdate.toString(), equalTo(expectedMapping.string())); @@ -99,7 +99,7 @@ public class UpdateMappingTests extends ESSingleNodeTestCase { CompressedXContent mappingBeforeUpdate = indexService.mapperService().documentMapper("type").mappingSource(); // simulate like in MetaDataMappingService#putMapping try { - indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingUpdate.bytes()), true).mapping(), true, false); + indexService.mapperService().merge("type", new CompressedXContent(mappingUpdate.bytes()), true, false); fail(); } catch (IllegalArgumentException e) { // expected @@ -123,14 +123,14 @@ public class UpdateMappingTests extends ESSingleNodeTestCase { mapperService.merge("type", new CompressedXContent(update.string()), false, false); fail(); } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), containsString("mapper [foo] cannot be changed from type [long] to [double]")); + assertThat(e.getMessage(), containsString("mapper [foo] of different type, current_type [long], merged_type [double]")); } try { mapperService.merge("type", new CompressedXContent(update.string()), false, false); fail(); } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), containsString("mapper [foo] cannot be changed from type [long] to [double]")); + assertThat(e.getMessage(), containsString("mapper [foo] of different type, current_type [long], merged_type [double]")); } assertTrue(mapperService.documentMapper("type").mapping().root().getMapper("foo") instanceof LongFieldMapper); diff --git a/core/src/test/java/org/elasticsearch/indices/mapping/UpdateMappingIntegrationIT.java b/core/src/test/java/org/elasticsearch/indices/mapping/UpdateMappingIntegrationIT.java index 32c9d3ed621..c6e9796ab60 100644 --- a/core/src/test/java/org/elasticsearch/indices/mapping/UpdateMappingIntegrationIT.java +++ b/core/src/test/java/org/elasticsearch/indices/mapping/UpdateMappingIntegrationIT.java @@ -149,7 +149,7 @@ public class UpdateMappingIntegrationIT extends ESIntegTestCase { .setSource("{\"type\":{\"properties\":{\"body\":{\"type\":\"integer\"}}}}").execute().actionGet(); fail("Expected MergeMappingException"); } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), containsString("mapper [body] cannot be changed from type [string] to [int]")); + assertThat(e.getMessage(), containsString("mapper [body] of different type, current_type [string], merged_type [integer]")); } } diff --git a/core/src/test/resources/org/elasticsearch/index/mapper/update/all_mapping_update_with_conflicts.json b/core/src/test/resources/org/elasticsearch/index/mapper/update/all_mapping_update_with_conflicts.json index 252aafefb08..bbeafa7edc7 100644 --- a/core/src/test/resources/org/elasticsearch/index/mapper/update/all_mapping_update_with_conflicts.json +++ b/core/src/test/resources/org/elasticsearch/index/mapper/update/all_mapping_update_with_conflicts.json @@ -2,7 +2,7 @@ "type": { "_all": { "store": false, - "enabled": false, + "enabled": true, "store_term_vectors": false, "store_term_vector_offsets": false, "store_term_vector_positions": false, diff --git a/plugins/mapper-size/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingTests.java b/plugins/mapper-size/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingTests.java index f9dcee1efe9..cc4eb682c8a 100644 --- a/plugins/mapper-size/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingTests.java +++ b/plugins/mapper-size/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingTests.java @@ -134,14 +134,13 @@ public class SizeMappingTests extends ESSingleNodeTestCase { String enabledMapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_size").field("enabled", true).endObject() .endObject().endObject().string(); - DocumentMapper enabledMapper = parser.parse("type", new CompressedXContent(enabledMapping)); + DocumentMapper enabledMapper = indexService.mapperService().merge("type", new CompressedXContent(enabledMapping), true, false); String disabledMapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("_size").field("enabled", false).endObject() .endObject().endObject().string(); - DocumentMapper disabledMapper = parser.parse("type", new CompressedXContent(disabledMapping)); + DocumentMapper disabledMapper = indexService.mapperService().merge("type", new CompressedXContent(disabledMapping), false, false); - enabledMapper.merge(disabledMapper.mapping(), false, false); - assertThat(enabledMapper.metadataMapper(SizeFieldMapper.class).enabled(), is(false)); + assertThat(disabledMapper.metadataMapper(SizeFieldMapper.class).enabled(), is(false)); } }