From adcc0683b8f1ca98dbaefe29ee3f181cd4c5d9e7 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Mon, 22 Jun 2015 14:00:10 -0700 Subject: [PATCH 1/6] Mappings: Restrict fields with the same name in different types to have the same core settings We currently are very lax about allowing data types to conflict for the same field name, across document types. This change makes the underlying map in MapperService a 1-1 map of field name to field type, and throws exception when new types are not compatible. To still allow changing a type, with parameters that are allowed to be changed, but for a field that exists in multiple types, a new parameter to index creation and put mapping API is added: update_all_types. This defaults to false, and the exception messages suggest using this parameter when trying to modify a setting that is allowed to be modified but is being limited by this restriction. There are also a couple changes which try to base fields from new types for dynamic mappings, and root mappers, on existing settings. For dynamic mappings this is important if the dynamic defaults have been changed. For root mappings, this is mostly just for backcompat when pre 2.0 root mappers could have their field type changed. fixes #8871 --- .../CreateIndexClusterStateUpdateRequest.java | 8 +- .../indices/create/CreateIndexRequest.java | 15 + .../create/CreateIndexRequestBuilder.java | 6 + .../create/TransportCreateIndexAction.java | 2 +- .../PutMappingClusterStateUpdateRequest.java | 11 + .../mapping/put/PutMappingRequest.java | 15 + .../mapping/put/PutMappingRequestBuilder.java | 6 + .../put/TransportPutMappingAction.java | 1 + .../metadata/MetaDataCreateIndexService.java | 4 +- .../metadata/MetaDataIndexAliasesService.java | 4 +- .../metadata/MetaDataMappingService.java | 12 +- .../index/fieldvisitor/FieldsVisitor.java | 15 +- .../index/mapper/DocumentFieldMappers.java | 72 ++-- .../index/mapper/DocumentMapper.java | 128 +++---- .../index/mapper/DocumentMapperParser.java | 4 +- .../index/mapper/DocumentParser.java | 337 +++++++++++------- .../index/mapper/FieldMapper.java | 9 + .../index/mapper/FieldMappersLookup.java | 193 ---------- .../index/mapper/FieldTypeLookup.java | 180 ++++++++++ .../index/mapper/MappedFieldType.java | 28 +- .../mapper/MappedFieldTypeReference.java | 50 +++ .../elasticsearch/index/mapper/Mapper.java | 8 + .../index/mapper/MapperBuilders.java | 36 +- .../index/mapper/MapperService.java | 150 +++----- .../index/mapper/MapperUtils.java | 14 +- .../index/mapper/MergeResult.java | 47 ++- .../index/mapper/ParseContext.java | 12 + .../mapper/core/AbstractFieldMapper.java | 53 ++- .../mapper/core/CompletionFieldMapper.java | 4 +- .../index/mapper/core/DateFieldMapper.java | 18 + .../index/mapper/core/NumberFieldMapper.java | 10 +- .../index/mapper/core/TypeParsers.java | 4 +- .../index/mapper/geo/GeoPointFieldMapper.java | 4 +- .../index/mapper/geo/GeoShapeFieldMapper.java | 6 +- .../index/mapper/internal/AllFieldMapper.java | 16 +- .../internal/FieldNamesFieldMapper.java | 23 +- .../index/mapper/internal/IdFieldMapper.java | 22 +- .../mapper/internal/IndexFieldMapper.java | 17 +- .../mapper/internal/ParentFieldMapper.java | 33 +- .../mapper/internal/RoutingFieldMapper.java | 16 +- .../mapper/internal/SizeFieldMapper.java | 20 +- .../mapper/internal/TimestampFieldMapper.java | 31 +- .../mapper/internal/TypeFieldMapper.java | 17 +- .../index/mapper/internal/UidFieldMapper.java | 17 +- .../cluster/IndicesClusterStateService.java | 4 +- .../indices/create/RestCreateIndexAction.java | 1 + .../mapping/put/RestPutMappingAction.java | 1 + .../termvectors/TermVectorsUnitTests.java | 2 +- .../exists/SimpleExistsTests.java | 2 +- .../gateway/RecoveryFromGatewayTests.java | 6 - .../org/elasticsearch/get/GetActionTests.java | 103 +----- .../index/engine/InternalEngineTests.java | 2 +- .../fielddata/ParentChildFieldDataTests.java | 4 +- ...upTests.java => FieldTypeLookupTests.java} | 167 ++++----- .../mapper/copyto/CopyToMapperTests.java | 4 +- .../core/TokenCountFieldMapperTests.java | 4 +- .../mapper/date/SimpleDateMappingTests.java | 2 +- .../mapper/geo/GeoPointFieldMapperTests.java | 4 +- .../mapper/geo/GeoShapeFieldMapperTests.java | 4 +- .../mapper/index/IndexTypeMapperTests.java | 4 +- .../internal/FieldNamesFieldMapperTests.java | 4 +- .../mapper/merge/TestMergeMapperTests.java | 18 +- .../mapper/multifield/MultiFieldTests.java | 2 +- .../merge/JavaMultiFieldMergeTests.java | 24 +- .../mapper/simple/SimpleMapperTests.java | 8 +- .../index/mapper/size/SizeMappingTests.java | 2 +- .../source/DefaultSourceMappingTests.java | 8 +- .../string/SimpleStringMappingTests.java | 4 +- .../timestamp/TimestampMappingTests.java | 10 +- .../index/mapper/ttl/TTLMappingTests.java | 24 +- .../mapper/update/UpdateMappingTests.java | 4 +- ...QueryParserFilterDateRangeFormatTests.java | 2 +- ...eryParserFilterDateRangeTimezoneTests.java | 2 +- .../query/SimpleIndexQueryParserTests.java | 2 +- .../search/child/AbstractChildTests.java | 4 +- .../percolator/RecoveryPercolatorTests.java | 5 +- .../bucket/nested/NestedAggregatorTest.java | 2 +- .../search/child/ChildQuerySearchTests.java | 4 +- .../child/ParentFieldLoadingBwcTest.java | 17 +- .../search/child/ParentFieldLoadingTest.java | 5 +- .../search/query/SearchQueryTests.java | 3 +- 81 files changed, 1144 insertions(+), 1002 deletions(-) delete mode 100644 core/src/main/java/org/elasticsearch/index/mapper/FieldMappersLookup.java create mode 100644 core/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java create mode 100644 core/src/main/java/org/elasticsearch/index/mapper/MappedFieldTypeReference.java rename core/src/test/java/org/elasticsearch/index/mapper/{FieldMappersLookupTests.java => FieldTypeLookupTests.java} (52%) diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java b/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java index 2da1f20bfd4..d915ad98165 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java @@ -41,6 +41,7 @@ public class CreateIndexClusterStateUpdateRequest extends ClusterStateUpdateRequ private final TransportMessage originalMessage; private final String cause; private final String index; + private final boolean updateAllTypes; private IndexMetaData.State state = IndexMetaData.State.OPEN; @@ -55,10 +56,11 @@ public class CreateIndexClusterStateUpdateRequest extends ClusterStateUpdateRequ private final Set blocks = Sets.newHashSet(); - CreateIndexClusterStateUpdateRequest(TransportMessage originalMessage, String cause, String index) { + CreateIndexClusterStateUpdateRequest(TransportMessage originalMessage, String cause, String index, boolean updateAllTypes) { this.originalMessage = originalMessage; this.cause = cause; this.index = index; + this.updateAllTypes = updateAllTypes; } public CreateIndexClusterStateUpdateRequest settings(Settings settings) { @@ -126,4 +128,8 @@ public class CreateIndexClusterStateUpdateRequest extends ClusterStateUpdateRequ public Set blocks() { return blocks; } + + public boolean updateAllTypes() { + return updateAllTypes; + } } diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java b/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java index 3a174484ef9..7ee2dc6161d 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequest.java @@ -72,6 +72,8 @@ public class CreateIndexRequest extends AcknowledgedRequest private final Map customs = newHashMap(); + private boolean updateAllTypes = false; + CreateIndexRequest() { } @@ -433,6 +435,17 @@ public class CreateIndexRequest extends AcknowledgedRequest return this.customs; } + /** True if all fields that span multiple types should be updated, false otherwise */ + public boolean updateAllTypes() { + return updateAllTypes; + } + + /** See {@link #updateAllTypes()} */ + public CreateIndexRequest updateAllTypes(boolean updateAllTypes) { + this.updateAllTypes = updateAllTypes; + return this; + } + @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); @@ -454,6 +467,7 @@ public class CreateIndexRequest extends AcknowledgedRequest for (int i = 0; i < aliasesSize; i++) { aliases.add(Alias.read(in)); } + updateAllTypes = in.readBoolean(); } @Override @@ -477,5 +491,6 @@ public class CreateIndexRequest extends AcknowledgedRequest for (Alias alias : aliases) { alias.writeTo(out); } + out.writeBoolean(updateAllTypes); } } diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestBuilder.java b/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestBuilder.java index 637c6d7ba08..2de6d4d57a0 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestBuilder.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestBuilder.java @@ -243,4 +243,10 @@ public class CreateIndexRequestBuilder extends AcknowledgedRequestBuilder im private String source; + private boolean updateAllTypes = false; + PutMappingRequest() { } @@ -236,6 +238,17 @@ public class PutMappingRequest extends AcknowledgedRequest im return this; } + /** True if all fields that span multiple types should be updated, false otherwise */ + public boolean updateAllTypes() { + return updateAllTypes; + } + + /** See {@link #updateAllTypes()} */ + public PutMappingRequest updateAllTypes(boolean updateAllTypes) { + this.updateAllTypes = updateAllTypes; + return this; + } + @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); @@ -243,6 +256,7 @@ public class PutMappingRequest extends AcknowledgedRequest im indicesOptions = IndicesOptions.readIndicesOptions(in); type = in.readOptionalString(); source = in.readString(); + updateAllTypes = in.readBoolean(); readTimeout(in); } @@ -253,6 +267,7 @@ public class PutMappingRequest extends AcknowledgedRequest im indicesOptions.writeIndicesOptions(out); out.writeOptionalString(type); out.writeString(source); + out.writeBoolean(updateAllTypes); writeTimeout(out); } } diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestBuilder.java b/core/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestBuilder.java index acf2c33c9dc..6b5d5d0d87e 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestBuilder.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestBuilder.java @@ -91,4 +91,10 @@ public class PutMappingRequestBuilder extends AcknowledgedRequestBuilder() { diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java index b53e218f216..f8b097b92e9 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java @@ -345,7 +345,7 @@ public class MetaDataCreateIndexService extends AbstractComponent { // first, add the default mapping if (mappings.containsKey(MapperService.DEFAULT_MAPPING)) { try { - mapperService.merge(MapperService.DEFAULT_MAPPING, new CompressedXContent(XContentFactory.jsonBuilder().map(mappings.get(MapperService.DEFAULT_MAPPING)).string()), false); + mapperService.merge(MapperService.DEFAULT_MAPPING, new CompressedXContent(XContentFactory.jsonBuilder().map(mappings.get(MapperService.DEFAULT_MAPPING)).string()), false, request.updateAllTypes()); } catch (Exception e) { removalReason = "failed on parsing default mapping on index creation"; throw new MapperParsingException("mapping [" + MapperService.DEFAULT_MAPPING + "]", e); @@ -357,7 +357,7 @@ public class MetaDataCreateIndexService extends AbstractComponent { } try { // apply the default here, its the first time we parse it - mapperService.merge(entry.getKey(), new CompressedXContent(XContentFactory.jsonBuilder().map(entry.getValue()).string()), true); + mapperService.merge(entry.getKey(), new CompressedXContent(XContentFactory.jsonBuilder().map(entry.getValue()).string()), true, request.updateAllTypes()); } catch (Exception e) { removalReason = "failed on parsing mappings on index creation"; throw new MapperParsingException("mapping [" + entry.getKey() + "]", e); diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java index e8b301597a0..7ab2c08f56d 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java @@ -101,11 +101,11 @@ public class MetaDataIndexAliasesService extends AbstractComponent { try { indexService = indicesService.createIndex(indexMetaData.index(), indexMetaData.settings(), clusterService.localNode().id()); if (indexMetaData.mappings().containsKey(MapperService.DEFAULT_MAPPING)) { - indexService.mapperService().merge(MapperService.DEFAULT_MAPPING, indexMetaData.mappings().get(MapperService.DEFAULT_MAPPING).source(), false); + indexService.mapperService().merge(MapperService.DEFAULT_MAPPING, indexMetaData.mappings().get(MapperService.DEFAULT_MAPPING).source(), false, false); } for (ObjectCursor cursor : indexMetaData.mappings().values()) { MappingMetaData mappingMetaData = cursor.value; - indexService.mapperService().merge(mappingMetaData.type(), mappingMetaData.source(), false); + indexService.mapperService().merge(mappingMetaData.type(), mappingMetaData.source(), false, false); } } catch (Exception e) { logger.warn("[{}] failed to temporary create in order to apply alias action", e, indexMetaData.index()); 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 ae6f32edd13..46ee0cdf736 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java @@ -193,7 +193,7 @@ public class MetaDataMappingService extends AbstractComponent { // only add the current relevant mapping (if exists) if (indexMetaData.mappings().containsKey(type)) { // don't apply the default mapping, it has been applied when the mapping was created - indexService.mapperService().merge(type, indexMetaData.mappings().get(type).source(), false); + indexService.mapperService().merge(type, indexMetaData.mappings().get(type).source(), false, true); } } } @@ -264,7 +264,7 @@ public class MetaDataMappingService extends AbstractComponent { continue; } - DocumentMapper updatedMapper = indexService.mapperService().merge(type, mappingSource, false); + DocumentMapper updatedMapper = indexService.mapperService().merge(type, mappingSource, false, true); processedRefreshes.add(type); // if we end up with the same mapping as the original once, ignore @@ -361,11 +361,11 @@ public class MetaDataMappingService extends AbstractComponent { indicesToClose.add(indexMetaData.index()); // make sure to add custom default mapping if exists if (indexMetaData.mappings().containsKey(MapperService.DEFAULT_MAPPING)) { - indexService.mapperService().merge(MapperService.DEFAULT_MAPPING, indexMetaData.mappings().get(MapperService.DEFAULT_MAPPING).source(), false); + indexService.mapperService().merge(MapperService.DEFAULT_MAPPING, indexMetaData.mappings().get(MapperService.DEFAULT_MAPPING).source(), false, request.updateAllTypes()); } // only add the current relevant mapping (if exists) if (indexMetaData.mappings().containsKey(request.type())) { - indexService.mapperService().merge(request.type(), indexMetaData.mappings().get(request.type()).source(), false); + indexService.mapperService().merge(request.type(), indexMetaData.mappings().get(request.type()).source(), false, request.updateAllTypes()); } } @@ -383,7 +383,7 @@ public class MetaDataMappingService extends AbstractComponent { newMapper = indexService.mapperService().parse(request.type(), new CompressedXContent(request.source()), existingMapper == null); if (existingMapper != null) { // first, simulate - MergeResult mergeResult = existingMapper.merge(newMapper.mapping(), true); + MergeResult mergeResult = existingMapper.merge(newMapper.mapping(), true, request.updateAllTypes()); // if we have conflicts, throw an exception if (mergeResult.hasConflicts()) { throw new MergeMappingException(mergeResult.buildConflicts()); @@ -438,7 +438,7 @@ public class MetaDataMappingService extends AbstractComponent { if (existingMappers.containsKey(entry.getKey())) { existingSource = existingMappers.get(entry.getKey()).mappingSource(); } - DocumentMapper mergedMapper = indexService.mapperService().merge(newMapper.type(), newMapper.mappingSource(), false); + DocumentMapper mergedMapper = indexService.mapperService().merge(newMapper.type(), newMapper.mappingSource(), false, request.updateAllTypes()); CompressedXContent updatedSource = mergedMapper.mappingSource(); if (existingSource != null) { diff --git a/core/src/main/java/org/elasticsearch/index/fieldvisitor/FieldsVisitor.java b/core/src/main/java/org/elasticsearch/index/fieldvisitor/FieldsVisitor.java index 38c1374ab31..5d63dfa0124 100644 --- a/core/src/main/java/org/elasticsearch/index/fieldvisitor/FieldsVisitor.java +++ b/core/src/main/java/org/elasticsearch/index/fieldvisitor/FieldsVisitor.java @@ -75,9 +75,20 @@ public abstract class FieldsVisitor extends StoredFieldVisitor { public void postProcess(DocumentMapper documentMapper) { for (Map.Entry> entry : fields().entrySet()) { - FieldMapper fieldMapper = documentMapper.mappers().indexName(entry.getKey()).mapper(); + String indexName = entry.getKey(); + FieldMapper fieldMapper = documentMapper.mappers().getMapper(indexName); if (fieldMapper == null) { - continue; + // it's possible index name doesn't match field name (legacy feature) + for (FieldMapper mapper : documentMapper.mappers()) { + if (mapper.fieldType().names().indexName().equals(indexName)) { + fieldMapper = mapper; + break; + } + } + if (fieldMapper == null) { + // no index name or full name found, so skip + continue; + } } List fieldValues = entry.getValue(); for (int i = 0; i < fieldValues.size(); i++) { 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 f7166ad769a..876f8b58755 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentFieldMappers.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentFieldMappers.java @@ -22,32 +22,38 @@ package org.elasticsearch.index.mapper; import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; 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.Collection; import java.util.Iterator; import java.util.Map; +import java.util.Set; /** * */ public final class DocumentFieldMappers implements Iterable { - private final FieldMappersLookup fieldMappers; + /** Full field name to mapper */ + private final CopyOnWriteHashMap fieldMappers; private final FieldNameAnalyzer indexAnalyzer; private final FieldNameAnalyzer searchAnalyzer; private final FieldNameAnalyzer searchQuoteAnalyzer; public DocumentFieldMappers(AnalysisService analysisService) { - this(new FieldMappersLookup(), new FieldNameAnalyzer(analysisService.defaultIndexAnalyzer()), - new FieldNameAnalyzer(analysisService.defaultSearchAnalyzer()), - new FieldNameAnalyzer(analysisService.defaultSearchQuoteAnalyzer())); + this(new CopyOnWriteHashMap(), + new FieldNameAnalyzer(analysisService.defaultIndexAnalyzer()), + new FieldNameAnalyzer(analysisService.defaultSearchAnalyzer()), + new FieldNameAnalyzer(analysisService.defaultSearchQuoteAnalyzer())); } - private DocumentFieldMappers(FieldMappersLookup fieldMappers, FieldNameAnalyzer indexAnalyzer, FieldNameAnalyzer searchAnalyzer, FieldNameAnalyzer searchQuoteAnalyzer) { + private DocumentFieldMappers(CopyOnWriteHashMap fieldMappers, FieldNameAnalyzer indexAnalyzer, FieldNameAnalyzer searchAnalyzer, FieldNameAnalyzer searchQuoteAnalyzer) { this.fieldMappers = fieldMappers; this.indexAnalyzer = indexAnalyzer; this.searchAnalyzer = searchAnalyzer; @@ -55,7 +61,10 @@ public final class DocumentFieldMappers implements Iterable { } public DocumentFieldMappers copyAndAllAll(Collection newMappers) { - FieldMappersLookup fieldMappers = this.fieldMappers.copyAndAddAll(newMappers); + CopyOnWriteHashMap map = this.fieldMappers; + for (FieldMapper fieldMapper : newMappers) { + map = map.copyAndPut(fieldMapper.fieldType().names().fullName(), fieldMapper); + } FieldNameAnalyzer indexAnalyzer = this.indexAnalyzer.copyAndAddAll(Collections2.transform(newMappers, new Function>() { @Override public Map.Entry apply(FieldMapper input) { @@ -74,22 +83,7 @@ public final class DocumentFieldMappers implements Iterable { return Maps.immutableEntry(input.fieldType().names().indexName(), (Analyzer)input.fieldType().searchQuoteAnalyzer()); } })); - return new DocumentFieldMappers(fieldMappers, indexAnalyzer, searchAnalyzer, searchQuoteAnalyzer); - } - - /** - * Looks up a field by its index name. - * - * Overriding index name for a field is no longer possibly, and only supported for backcompat. - * This function first attempts to lookup the field by full name, and only when that fails, - * does a full scan of all field mappers, collecting those with this index name. - * - * This will be removed in 3.0, once backcompat for overriding index name is removed. - * @deprecated Use {@link #getMapper(String)} - */ - @Deprecated - public FieldMappers indexName(String indexName) { - return fieldMappers.indexName(indexName); + return new DocumentFieldMappers(map, indexAnalyzer, searchAnalyzer, searchQuoteAnalyzer); } /** Returns the mapper for the given field */ @@ -97,23 +91,29 @@ public final class DocumentFieldMappers implements Iterable { return fieldMappers.get(field); } - Collection simpleMatchToIndexNames(String pattern) { - return fieldMappers.simpleMatchToIndexNames(pattern); - } - public Collection simpleMatchToFullName(String pattern) { - return fieldMappers.simpleMatchToFullName(pattern); - } - - /** - * Tries to find first based on fullName, then by indexName. - */ - FieldMappers smartName(String name) { - return fieldMappers.smartName(name); + Set fields = Sets.newHashSet(); + for (FieldMapper fieldMapper : this) { + if (Regex.simpleMatch(pattern, fieldMapper.fieldType().names().fullName())) { + fields.add(fieldMapper.fieldType().names().fullName()); + } else if (Regex.simpleMatch(pattern, fieldMapper.fieldType().names().indexName())) { + fields.add(fieldMapper.fieldType().names().fullName()); + } + } + return fields; } public FieldMapper smartNameFieldMapper(String name) { - return fieldMappers.smartNameFieldMapper(name); + FieldMapper fieldMapper = getMapper(name); + if (fieldMapper != null) { + return fieldMapper; + } + for (FieldMapper otherFieldMapper : this) { + if (otherFieldMapper.fieldType().names().indexName().equals(name)) { + return otherFieldMapper; + } + } + return null; } /** @@ -145,6 +145,6 @@ public final class DocumentFieldMappers implements Iterable { } public Iterator iterator() { - return fieldMappers.iterator(); + return fieldMappers.values().iterator(); } } 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 825d0ddc628..773ff9b1099 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java @@ -23,7 +23,6 @@ import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; - import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.search.DocIdSet; import org.apache.lucene.search.DocIdSetIterator; @@ -32,7 +31,6 @@ import org.apache.lucene.search.Query; import org.elasticsearch.ElasticsearchGenerationException; import org.elasticsearch.Version; import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.collect.MapBuilder; import org.elasticsearch.common.compress.CompressedXContent; @@ -43,6 +41,7 @@ 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.fielddata.FieldDataType; import org.elasticsearch.index.mapper.Mapping.SourceTransform; import org.elasticsearch.index.mapper.internal.AllFieldMapper; import org.elasticsearch.index.mapper.internal.FieldNamesFieldMapper; @@ -96,28 +95,32 @@ public class DocumentMapper implements ToXContent { private final Mapper.BuilderContext builderContext; - public Builder(String index, Settings indexSettings, RootObjectMapper.Builder builder) { + public Builder(String index, Settings indexSettings, RootObjectMapper.Builder builder, MapperService mapperService) { this.index = index; this.indexSettings = indexSettings; this.builderContext = new Mapper.BuilderContext(indexSettings, new ContentPath(1)); this.rootObjectMapper = builder.build(builderContext); + // TODO: find a cleaner way to handle existing root mappings and using their field type as the default. + // the vast majority of these root mappers only need the existing type for backwards compatibility, since + // the pre 2.0 field type settings could be modified + // UID first so it will be the first stored field to load (so will benefit from "fields: []" early termination - this.rootMappers.put(UidFieldMapper.class, new UidFieldMapper(indexSettings)); - this.rootMappers.put(IdFieldMapper.class, new IdFieldMapper(indexSettings)); - this.rootMappers.put(RoutingFieldMapper.class, new RoutingFieldMapper(indexSettings)); + this.rootMappers.put(UidFieldMapper.class, new UidFieldMapper(indexSettings, mapperService.fullName(UidFieldMapper.NAME))); + this.rootMappers.put(IdFieldMapper.class, new IdFieldMapper(indexSettings, mapperService.fullName(IdFieldMapper.NAME))); + this.rootMappers.put(RoutingFieldMapper.class, new RoutingFieldMapper(indexSettings, mapperService.fullName(RoutingFieldMapper.NAME))); // add default mappers, order is important (for example analyzer should come before the rest to set context.analyzer) - this.rootMappers.put(SizeFieldMapper.class, new SizeFieldMapper(indexSettings)); - this.rootMappers.put(IndexFieldMapper.class, new IndexFieldMapper(indexSettings)); + this.rootMappers.put(SizeFieldMapper.class, new SizeFieldMapper(indexSettings, mapperService.fullName(SizeFieldMapper.NAME))); + this.rootMappers.put(IndexFieldMapper.class, new IndexFieldMapper(indexSettings, mapperService.fullName(IndexFieldMapper.NAME))); this.rootMappers.put(SourceFieldMapper.class, new SourceFieldMapper(indexSettings)); - this.rootMappers.put(TypeFieldMapper.class, new TypeFieldMapper(indexSettings)); - this.rootMappers.put(AllFieldMapper.class, new AllFieldMapper(indexSettings)); - this.rootMappers.put(TimestampFieldMapper.class, new TimestampFieldMapper(indexSettings)); + this.rootMappers.put(TypeFieldMapper.class, new TypeFieldMapper(indexSettings, mapperService.fullName(TypeFieldMapper.NAME))); + this.rootMappers.put(AllFieldMapper.class, new AllFieldMapper(indexSettings, mapperService.fullName(AllFieldMapper.NAME))); + this.rootMappers.put(TimestampFieldMapper.class, new TimestampFieldMapper(indexSettings, mapperService.fullName(TimestampFieldMapper.NAME))); this.rootMappers.put(TTLFieldMapper.class, new TTLFieldMapper(indexSettings)); this.rootMappers.put(VersionFieldMapper.class, new VersionFieldMapper(indexSettings)); - this.rootMappers.put(ParentFieldMapper.class, new ParentFieldMapper(indexSettings)); + this.rootMappers.put(ParentFieldMapper.class, new ParentFieldMapper(indexSettings, mapperService.fullName(ParentFieldMapper.NAME))); // _field_names last so that it can see all other fields - this.rootMappers.put(FieldNamesFieldMapper.class, new FieldNamesFieldMapper(indexSettings)); + this.rootMappers.put(FieldNamesFieldMapper.class, new FieldNamesFieldMapper(indexSettings, mapperService.fullName(FieldNamesFieldMapper.NAME))); } public Builder meta(ImmutableMap meta) { @@ -393,87 +396,40 @@ public class DocumentMapper implements ToXContent { return DocumentParser.transformSourceAsMap(mapping, sourceAsMap); } - private void addFieldMappers(Collection fieldMappers) { - assert mappingLock.isWriteLockedByCurrentThread(); - this.fieldMappers = this.fieldMappers.copyAndAllAll(fieldMappers); - mapperService.addFieldMappers(fieldMappers); - } - public boolean isParent(String type) { return mapperService.getParentTypes().contains(type); } - private void addObjectMappers(Collection objectMappers) { + private void addMappers(Collection objectMappers, Collection fieldMappers) { assert mappingLock.isWriteLockedByCurrentThread(); - MapBuilder builder = MapBuilder.newMapBuilder(this.objectMappers); - for (ObjectMapper objectMapper : objectMappers) { - builder.put(objectMapper.fullPath(), objectMapper); - if (objectMapper.nested().isNested()) { - hasNestedObjects = true; - } + // first ensure we don't have any incompatible new fields + mapperService.checkNewMappersCompatibility(objectMappers, fieldMappers, true); + + // update mappers for this document type + MapBuilder builder = MapBuilder.newMapBuilder(this.objectMappers); + for (ObjectMapper objectMapper : objectMappers) { + builder.put(objectMapper.fullPath(), objectMapper); + if (objectMapper.nested().isNested()) { + hasNestedObjects = true; } - this.objectMappers = builder.immutableMap(); - mapperService.addObjectMappers(objectMappers); - } - - private MergeResult newMergeContext(boolean simulate) { - return new MergeResult(simulate) { - - final List conflicts = new ArrayList<>(); - final List newFieldMappers = new ArrayList<>(); - final List newObjectMappers = new ArrayList<>(); - - @Override - public void addFieldMappers(Collection fieldMappers) { - assert simulate() == false; - newFieldMappers.addAll(fieldMappers); - } - - @Override - public void addObjectMappers(Collection objectMappers) { - assert simulate() == false; - newObjectMappers.addAll(objectMappers); - } - - @Override - public Collection getNewFieldMappers() { - return newFieldMappers; - } - - @Override - public Collection getNewObjectMappers() { - return newObjectMappers; - } - - @Override - public void addConflict(String mergeFailure) { - conflicts.add(mergeFailure); - } - - @Override - public boolean hasConflicts() { - return conflicts.isEmpty() == false; - } - - @Override - public String[] buildConflicts() { - return conflicts.toArray(Strings.EMPTY_ARRAY); - } - - }; - } - - public MergeResult merge(Mapping mapping, boolean simulate) { - try (ReleasableLock lock = mappingWriteLock.acquire()) { - final MergeResult mergeResult = newMergeContext(simulate); - this.mapping.merge(mapping, mergeResult); - if (simulate == false) { - addFieldMappers(mergeResult.getNewFieldMappers()); - addObjectMappers(mergeResult.getNewObjectMappers()); - refreshSource(); } - return mergeResult; + this.objectMappers = builder.immutableMap(); + this.fieldMappers = this.fieldMappers.copyAndAllAll(fieldMappers); + + // finally update for the entire index + mapperService.addMappers(objectMappers, fieldMappers); } + + public MergeResult merge(Mapping mapping, boolean simulate, boolean updateAllTypes) { + try (ReleasableLock lock = mappingWriteLock.acquire()) { + final MergeResult mergeResult = new MergeResult(simulate, updateAllTypes); + this.mapping.merge(mapping, mergeResult); + if (simulate == false) { + addMappers(mergeResult.getNewObjectMappers(), mergeResult.getNewFieldMappers()); + refreshSource(); + } + return mergeResult; + } } private void refreshSource() throws ElasticsearchGenerationException { 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 d5a3ff1f9ad..1954b4e8c16 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentMapperParser.java @@ -167,7 +167,7 @@ public class DocumentMapperParser extends AbstractIndexComponent { } public Mapper.TypeParser.ParserContext parserContext() { - return new Mapper.TypeParser.ParserContext(analysisService, similarityLookupService, typeParsers, indexVersionCreated); + return new Mapper.TypeParser.ParserContext(analysisService, similarityLookupService, mapperService, typeParsers, indexVersionCreated); } public DocumentMapper parse(String source) throws MapperParsingException { @@ -227,7 +227,7 @@ public class DocumentMapperParser extends AbstractIndexComponent { Mapper.TypeParser.ParserContext parserContext = parserContext(); // parse RootObjectMapper - DocumentMapper.Builder docBuilder = doc(index.name(), indexSettings, (RootObjectMapper.Builder) rootObjectTypeParser.parse(type, mapping, parserContext)); + DocumentMapper.Builder docBuilder = doc(index.name(), indexSettings, (RootObjectMapper.Builder) rootObjectTypeParser.parse(type, mapping, parserContext), mapperService); Iterator> iterator = mapping.entrySet().iterator(); // parse DocumentMapper while(iterator.hasNext()) { 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 79ca3982442..f8e422f1c81 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java @@ -33,6 +33,13 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.index.mapper.core.AbstractFieldMapper; +import org.elasticsearch.index.mapper.core.NumberFieldMapper; +import org.elasticsearch.index.mapper.core.StringFieldMapper; +import org.elasticsearch.index.mapper.core.AbstractFieldMapper.Builder; +import org.elasticsearch.index.mapper.core.DateFieldMapper.DateFieldType; +import org.elasticsearch.index.mapper.core.LongFieldMapper.LongFieldType; +import org.elasticsearch.index.mapper.core.StringFieldMapper.StringFieldType; import org.elasticsearch.index.mapper.internal.TypeFieldMapper; import org.elasticsearch.index.mapper.internal.UidFieldMapper; import org.elasticsearch.index.mapper.object.ArrayValueMapperParser; @@ -438,6 +445,172 @@ class DocumentParser implements Closeable { } } + private static Mapper.Builder createBuilderFromFieldType(final ParseContext context, MappedFieldType fieldType, String currentFieldName) { + Mapper.Builder builder = null; + if (fieldType instanceof StringFieldType) { + builder = context.root().findTemplateBuilder(context, currentFieldName, "string"); + if (builder == null) { + builder = MapperBuilders.stringField(currentFieldName); + } + } else if (fieldType instanceof DateFieldType) { + builder = context.root().findTemplateBuilder(context, currentFieldName, "date"); + if (builder == null) { + builder = MapperBuilders.dateField(currentFieldName); + } + } else if (fieldType.numericType() != null) { + switch (fieldType.numericType()) { + case LONG: + builder = context.root().findTemplateBuilder(context, currentFieldName, "long"); + if (builder == null) { + builder = MapperBuilders.longField(currentFieldName); + } + case DOUBLE: + builder = context.root().findTemplateBuilder(context, currentFieldName, "double"); + if (builder == null) { + builder = MapperBuilders.doubleField(currentFieldName); + } + break; + case INT: + builder = context.root().findTemplateBuilder(context, currentFieldName, "integer"); + if (builder == null) { + builder = MapperBuilders.integerField(currentFieldName); + } + case FLOAT: + builder = context.root().findTemplateBuilder(context, currentFieldName, "float"); + if (builder == null) { + builder = MapperBuilders.floatField(currentFieldName); + } + break; + default: + throw new AssertionError("Unexpected numeric type " + fieldType.numericType()); + } + } + return builder; + } + + private static Mapper.Builder createBuilderFromDynamicValue(final ParseContext context, XContentParser.Token token, String currentFieldName) throws IOException { + if (token == XContentParser.Token.VALUE_STRING) { + // do a quick test to see if its fits a dynamic template, if so, use it. + // we need to do it here so we can handle things like attachment templates, where calling + // text (to see if its a date) causes the binary value to be cleared + { + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "string", null); + if (builder != null) { + return builder; + } + } + + if (context.root().dateDetection()) { + String text = context.parser().text(); + // a safe check since "1" gets parsed as well + if (Strings.countOccurrencesOf(text, ":") > 1 || Strings.countOccurrencesOf(text, "-") > 1 || Strings.countOccurrencesOf(text, "/") > 1) { + for (FormatDateTimeFormatter dateTimeFormatter : context.root().dynamicDateTimeFormatters()) { + try { + dateTimeFormatter.parser().parseMillis(text); + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "date"); + if (builder == null) { + builder = MapperBuilders.dateField(currentFieldName).dateTimeFormatter(dateTimeFormatter); + } + return builder; + } catch (Exception e) { + // failure to parse this, continue + } + } + } + } + if (context.root().numericDetection()) { + String text = context.parser().text(); + try { + Long.parseLong(text); + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "long"); + if (builder == null) { + builder = MapperBuilders.longField(currentFieldName); + } + return builder; + } catch (Exception e) { + // not a long number + } + try { + Double.parseDouble(text); + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "double"); + if (builder == null) { + builder = MapperBuilders.doubleField(currentFieldName); + } + return builder; + } catch (Exception e) { + // not a long number + } + } + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "string"); + if (builder == null) { + builder = MapperBuilders.stringField(currentFieldName); + } + return builder; + } else if (token == XContentParser.Token.VALUE_NUMBER) { + XContentParser.NumberType numberType = context.parser().numberType(); + if (numberType == XContentParser.NumberType.INT) { + if (context.parser().estimatedNumberType()) { + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "long"); + if (builder == null) { + builder = MapperBuilders.longField(currentFieldName); + } + return builder; + } else { + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "integer"); + if (builder == null) { + builder = MapperBuilders.integerField(currentFieldName); + } + return builder; + } + } else if (numberType == XContentParser.NumberType.LONG) { + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "long"); + if (builder == null) { + builder = MapperBuilders.longField(currentFieldName); + } + return builder; + } else if (numberType == XContentParser.NumberType.FLOAT) { + if (context.parser().estimatedNumberType()) { + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "double"); + if (builder == null) { + builder = MapperBuilders.doubleField(currentFieldName); + } + return builder; + } else { + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "float"); + if (builder == null) { + builder = MapperBuilders.floatField(currentFieldName); + } + return builder; + } + } else if (numberType == XContentParser.NumberType.DOUBLE) { + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "double"); + if (builder == null) { + builder = MapperBuilders.doubleField(currentFieldName); + } + return builder; + } + } else if (token == XContentParser.Token.VALUE_BOOLEAN) { + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "boolean"); + if (builder == null) { + builder = MapperBuilders.booleanField(currentFieldName); + } + return builder; + } else if (token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) { + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "binary"); + if (builder == null) { + builder = MapperBuilders.binaryField(currentFieldName); + } + return builder; + } else { + Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, null); + if (builder != null) { + return builder; + } + } + // TODO how do we identify dynamically that its a binary value? + throw new IllegalStateException("Can't handle serializing a dynamic type with content token [" + token + "] and field name [" + currentFieldName + "]"); + } + private static ObjectMapper parseDynamicValue(final ParseContext context, ObjectMapper parentMapper, String currentFieldName, XContentParser.Token token) throws IOException { ObjectMapper.Dynamic dynamic = parentMapper.dynamic(); if (dynamic == null) { @@ -449,140 +622,33 @@ class DocumentParser implements Closeable { if (dynamic == ObjectMapper.Dynamic.FALSE) { return null; } - Mapper mapper = null; - Mapper.BuilderContext builderContext = new Mapper.BuilderContext(context.indexSettings(), context.path()); - if (token == XContentParser.Token.VALUE_STRING) { - boolean resolved = false; - - // do a quick test to see if its fits a dynamic template, if so, use it. - // we need to do it here so we can handle things like attachment templates, where calling - // text (to see if its a date) causes the binary value to be cleared - if (!resolved) { - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "string", null); - if (builder != null) { - mapper = builder.build(builderContext); - resolved = true; - } - } - - if (!resolved && context.root().dateDetection()) { - String text = context.parser().text(); - // a safe check since "1" gets parsed as well - if (Strings.countOccurrencesOf(text, ":") > 1 || Strings.countOccurrencesOf(text, "-") > 1 || Strings.countOccurrencesOf(text, "/") > 1) { - for (FormatDateTimeFormatter dateTimeFormatter : context.root().dynamicDateTimeFormatters()) { - try { - dateTimeFormatter.parser().parseMillis(text); - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "date"); - if (builder == null) { - builder = MapperBuilders.dateField(currentFieldName).dateTimeFormatter(dateTimeFormatter); - } - mapper = builder.build(builderContext); - resolved = true; - break; - } catch (Exception e) { - // failure to parse this, continue - } - } - } - } - if (!resolved && context.root().numericDetection()) { - String text = context.parser().text(); - try { - Long.parseLong(text); - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "long"); - if (builder == null) { - builder = MapperBuilders.longField(currentFieldName); - } - mapper = builder.build(builderContext); - resolved = true; - } catch (Exception e) { - // not a long number - } - if (!resolved) { - try { - Double.parseDouble(text); - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "double"); - if (builder == null) { - builder = MapperBuilders.doubleField(currentFieldName); - } - mapper = builder.build(builderContext); - resolved = true; - } catch (Exception e) { - // not a long number - } - } - } - if (!resolved) { - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "string"); - if (builder == null) { - builder = MapperBuilders.stringField(currentFieldName); - } - mapper = builder.build(builderContext); - } - } else if (token == XContentParser.Token.VALUE_NUMBER) { - XContentParser.NumberType numberType = context.parser().numberType(); - if (numberType == XContentParser.NumberType.INT) { - if (context.parser().estimatedNumberType()) { - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "long"); - if (builder == null) { - builder = MapperBuilders.longField(currentFieldName); - } - mapper = builder.build(builderContext); - } else { - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "integer"); - if (builder == null) { - builder = MapperBuilders.integerField(currentFieldName); - } - mapper = builder.build(builderContext); - } - } else if (numberType == XContentParser.NumberType.LONG) { - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "long"); - if (builder == null) { - builder = MapperBuilders.longField(currentFieldName); - } - mapper = builder.build(builderContext); - } else if (numberType == XContentParser.NumberType.FLOAT) { - if (context.parser().estimatedNumberType()) { - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "double"); - if (builder == null) { - builder = MapperBuilders.doubleField(currentFieldName); - } - mapper = builder.build(builderContext); - } else { - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "float"); - if (builder == null) { - builder = MapperBuilders.floatField(currentFieldName); - } - mapper = builder.build(builderContext); - } - } else if (numberType == XContentParser.NumberType.DOUBLE) { - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "double"); - if (builder == null) { - builder = MapperBuilders.doubleField(currentFieldName); - } - mapper = builder.build(builderContext); - } - } else if (token == XContentParser.Token.VALUE_BOOLEAN) { - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "boolean"); - if (builder == null) { - builder = MapperBuilders.booleanField(currentFieldName); - } - mapper = builder.build(builderContext); - } else if (token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) { - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, "binary"); - if (builder == null) { - builder = MapperBuilders.binaryField(currentFieldName); - } - mapper = builder.build(builderContext); - } else { - Mapper.Builder builder = context.root().findTemplateBuilder(context, currentFieldName, null); - if (builder != null) { - mapper = builder.build(builderContext); - } else { - // TODO how do we identify dynamically that its a binary value? - throw new IllegalStateException("Can't handle serializing a dynamic type with content token [" + token + "] and field name [" + currentFieldName + "]"); + final Mapper.BuilderContext builderContext = new Mapper.BuilderContext(context.indexSettings(), context.path()); + final MappedFieldType existingFieldType = context.mapperService().fullName(context.path().fullPathAsText(currentFieldName)); + Mapper.Builder builder = null; + if (existingFieldType != null) { + // create a builder of the same type + builder = createBuilderFromFieldType(context, existingFieldType, currentFieldName); + } + if (builder == null) { + builder = createBuilderFromDynamicValue(context, token, currentFieldName); + } + if (existingFieldType != null) { + // best-effort to not introduce a conflict + if (builder instanceof StringFieldMapper.Builder) { + StringFieldMapper.Builder stringBuilder = (StringFieldMapper.Builder) builder; + stringBuilder.store(existingFieldType.stored()); + stringBuilder.indexOptions(existingFieldType.indexOptions()); + stringBuilder.omitNorms(existingFieldType.omitNorms()); + stringBuilder.docValues(existingFieldType.hasDocValues()); + } else if (builder instanceof NumberFieldMapper.Builder) { + NumberFieldMapper.Builder numberBuilder = (NumberFieldMapper.Builder) builder; + numberBuilder.store(existingFieldType.stored()); + numberBuilder.indexOptions(existingFieldType.indexOptions()); + numberBuilder.omitNorms(existingFieldType.omitNorms()); + numberBuilder.docValues(existingFieldType.hasDocValues()); } } + Mapper mapper = builder.build(builderContext); mapper = parseAndMergeUpdate(mapper, context); @@ -621,10 +687,9 @@ class DocumentParser implements Closeable { /** Creates an copy of the current field with given field name and boost */ private static void parseCopy(String field, ParseContext context) throws IOException { - // TODO: this should not be indexName... - FieldMappers mappers = context.docMapper().mappers().indexName(field); - if (mappers != null && !mappers.isEmpty()) { - mappers.mapper().parse(context); + FieldMapper fieldMapper = context.docMapper().mappers().getMapper(field); + if (fieldMapper != null) { + fieldMapper.parse(context); } else { // The path of the dest field might be completely different from the current one so we need to reset it context = context.overridePath(new ContentPath(0)); 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 20c258783f1..4c3004d3247 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java @@ -32,6 +32,15 @@ public interface FieldMapper extends Mapper { MappedFieldType fieldType(); + /** Returns a reference to the MappedFieldType for this mapper. */ + MappedFieldTypeReference fieldTypeReference(); + + /** + * Updates the reference to this field's MappedFieldType. + * Implementations should assert equality of the underlying field type + */ + void setFieldTypeReference(MappedFieldTypeReference ref); + /** * List of fields where this field should be copied to */ diff --git a/core/src/main/java/org/elasticsearch/index/mapper/FieldMappersLookup.java b/core/src/main/java/org/elasticsearch/index/mapper/FieldMappersLookup.java deleted file mode 100644 index eda694a939d..00000000000 --- a/core/src/main/java/org/elasticsearch/index/mapper/FieldMappersLookup.java +++ /dev/null @@ -1,193 +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; - -import com.google.common.collect.Sets; -import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.collect.CopyOnWriteHashMap; -import org.elasticsearch.common.regex.Regex; - -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.Set; - -/** - * A class that holds a map of field mappers from name, index name, and full name. - */ -class FieldMappersLookup implements Iterable { - - /** Full field name to mappers */ - private final CopyOnWriteHashMap mappers; - - /** Create a new empty instance. */ - public FieldMappersLookup() { - mappers = new CopyOnWriteHashMap<>(); - } - - private FieldMappersLookup(CopyOnWriteHashMap map) { - mappers = map; - } - - /** - * Return a new instance that contains the union of this instance and the provided mappers. - */ - public FieldMappersLookup copyAndAddAll(Collection newMappers) { - CopyOnWriteHashMap map = this.mappers; - - for (FieldMapper mapper : newMappers) { - String key = mapper.fieldType().names().fullName(); - FieldMappers mappers = map.get(key); - - if (mappers == null) { - mappers = new FieldMappers(mapper); - } else { - mappers = mappers.concat(mapper); - } - map = map.copyAndPut(key, mappers); - } - return new FieldMappersLookup(map); - } - - /** - * Returns the field mappers based on the mapper index name. - * NOTE: this only exists for backcompat support and if the index name - * does not match it's field name, this is a linear time operation - * @deprecated Use {@link #get(String)} - */ - @Deprecated - public FieldMappers indexName(String indexName) { - FieldMappers fieldMappers = fullName(indexName); - if (fieldMappers != null) { - if (fieldMappers.mapper().fieldType().names().indexName().equals(indexName)) { - return fieldMappers; - } - } - fieldMappers = new FieldMappers(); - for (FieldMapper mapper : this) { - if (mapper.fieldType().names().indexName().equals(indexName)) { - fieldMappers = fieldMappers.concat(mapper); - } - } - if (fieldMappers.isEmpty()) { - return null; - } - return fieldMappers; - } - - /** - * Returns the field mappers based on the mapper full name. - */ - public FieldMappers fullName(String fullName) { - return mappers.get(fullName); - } - - /** Returns the mapper for the given field */ - public FieldMapper get(String field) { - FieldMappers fieldMappers = mappers.get(field); - if (fieldMappers == null) { - return null; - } - if (fieldMappers.mappers().size() != 1) { - throw new IllegalStateException("Mapper for field [" + field + "] should be unique"); - } - return fieldMappers.mapper(); - } - - /** - * Returns a list of the index names of a simple match regex like pattern against full name and index name. - */ - public Collection simpleMatchToIndexNames(String pattern) { - Set fields = Sets.newHashSet(); - for (FieldMapper fieldMapper : this) { - if (Regex.simpleMatch(pattern, fieldMapper.fieldType().names().fullName())) { - fields.add(fieldMapper.fieldType().names().indexName()); - } else if (Regex.simpleMatch(pattern, fieldMapper.fieldType().names().indexName())) { - fields.add(fieldMapper.fieldType().names().indexName()); - } - } - return fields; - } - - /** - * Returns a list of the full names of a simple match regex like pattern against full name and index name. - */ - public Collection simpleMatchToFullName(String pattern) { - Set fields = Sets.newHashSet(); - for (FieldMapper fieldMapper : this) { - if (Regex.simpleMatch(pattern, fieldMapper.fieldType().names().fullName())) { - fields.add(fieldMapper.fieldType().names().fullName()); - } else if (Regex.simpleMatch(pattern, fieldMapper.fieldType().names().indexName())) { - fields.add(fieldMapper.fieldType().names().fullName()); - } - } - return fields; - } - - /** - * Tries to find first based on {@link #fullName(String)}, then by {@link #indexName(String)}. - */ - @Nullable - FieldMappers smartName(String name) { - FieldMappers fieldMappers = fullName(name); - if (fieldMappers != null) { - return fieldMappers; - } - return indexName(name); - } - - /** - * Tries to find first based on {@link #fullName(String)}, then by {@link #indexName(String)} - * and return the first mapper for it (see {@link org.elasticsearch.index.mapper.FieldMappers#mapper()}). - */ - @Nullable - public FieldMapper smartNameFieldMapper(String name) { - FieldMappers fieldMappers = smartName(name); - if (fieldMappers == null) { - return null; - } - return fieldMappers.mapper(); - } - - public Iterator iterator() { - final Iterator fieldsItr = mappers.values().iterator(); - if (fieldsItr.hasNext() == false) { - return Collections.emptyIterator(); - } - return new Iterator() { - Iterator fieldValuesItr = fieldsItr.next().iterator(); - @Override - public boolean hasNext() { - return fieldsItr.hasNext() || fieldValuesItr.hasNext(); - } - @Override - public FieldMapper next() { - if (fieldValuesItr.hasNext() == false && fieldsItr.hasNext()) { - fieldValuesItr = fieldsItr.next().iterator(); - } - return fieldValuesItr.next(); - } - @Override - public void remove() { - throw new UnsupportedOperationException("cannot remove field mapper from lookup"); - } - }; - } -} diff --git a/core/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java b/core/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java new file mode 100644 index 00000000000..23c77fd5248 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java @@ -0,0 +1,180 @@ +/* + * 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 com.google.common.base.Function; +import com.google.common.collect.Iterators; +import com.google.common.collect.Sets; +import org.elasticsearch.common.collect.CopyOnWriteHashMap; +import org.elasticsearch.common.regex.Regex; +import org.elasticsearch.index.mapper.object.ObjectMapper; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +/** + * An immutable container for looking up {@link MappedFieldType}s by their name. + */ +class FieldTypeLookup implements Iterable { + private static final Function UNWRAPPER = new Function() { + @Override + public MappedFieldType apply(MappedFieldTypeReference ref) { + return ref.get(); + } + }; + + /** Full field name to field type */ + private final CopyOnWriteHashMap fullNameToFieldType; + + /** Index field name to field type */ + private final CopyOnWriteHashMap indexNameToFieldType; + + /** Create a new empty instance. */ + public FieldTypeLookup() { + fullNameToFieldType = new CopyOnWriteHashMap<>(); + indexNameToFieldType = new CopyOnWriteHashMap<>(); + } + + private FieldTypeLookup(CopyOnWriteHashMap fullName, CopyOnWriteHashMap indexName) { + fullNameToFieldType = fullName; + indexNameToFieldType = indexName; + } + + /** + * Return a new instance that contains the union of this instance and the field types + * 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(Collection newFieldMappers) { + CopyOnWriteHashMap fullName = this.fullNameToFieldType; + CopyOnWriteHashMap indexName = this.indexNameToFieldType; + + for (FieldMapper fieldMapper : newFieldMappers) { + 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 { + // 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()); + } + } + return new FieldTypeLookup(fullName, indexName); + } + + /** + * Checks if the give mapper's field types are compatibile with existing field types. + * If any are not compatible, an IllegalArgumentException is thrown. + * If updateAllTypes is true, only basic compatibility is checked. + */ + public void checkCompatibility(Collection newFieldMappers, boolean updateAllTypes) { + for (FieldMapper fieldMapper : newFieldMappers) { + MappedFieldTypeReference ref = fullNameToFieldType.get(fieldMapper.fieldType().names().fullName()); + if (ref != null) { + boolean strict = ref.getRefCount() > 1 && updateAllTypes == false; + List conflicts = new ArrayList<>(); + 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" + conflicts.toString()); + } + } + + // field type for the index name must be compatible too + MappedFieldTypeReference indexNameRef = fullNameToFieldType.get(fieldMapper.fieldType().names().indexName()); + if (indexNameRef != null) { + boolean strict = indexNameRef.getRefCount() > 1 && updateAllTypes == false; + List conflicts = new ArrayList<>(); + 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()); + } + } + } + } + + /** 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(); + } + + /** 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(); + } + + /** + * Returns a list of the index names of a simple match regex like pattern against full name and index name. + */ + public Collection simpleMatchToIndexNames(String pattern) { + Set fields = Sets.newHashSet(); + for (MappedFieldType fieldType : this) { + if (Regex.simpleMatch(pattern, fieldType.names().fullName())) { + fields.add(fieldType.names().indexName()); + } else if (Regex.simpleMatch(pattern, fieldType.names().indexName())) { + fields.add(fieldType.names().indexName()); + } + } + return fields; + } + + /** + * Returns a list of the full names of a simple match regex like pattern against full name and index name. + */ + public Collection simpleMatchToFullName(String pattern) { + Set fields = Sets.newHashSet(); + for (MappedFieldType fieldType : this) { + if (Regex.simpleMatch(pattern, fieldType.names().fullName())) { + fields.add(fieldType.names().fullName()); + } else if (Regex.simpleMatch(pattern, fieldType.names().indexName())) { + fields.add(fieldType.names().fullName()); + } + } + return fields; + } + + public Iterator iterator() { + return Iterators.transform(fullNameToFieldType.values().iterator(), UNWRAPPER); + } +} diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java index 12c8e3a1037..9480ae83b86 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java @@ -20,7 +20,6 @@ package org.elasticsearch.index.mapper; import com.google.common.base.Strings; -import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.FieldType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.Term; @@ -38,7 +37,6 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.action.fieldstats.FieldStats; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.lucene.BytesRefs; -import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.index.analysis.NamedAnalyzer; import org.elasticsearch.index.fielddata.FieldDataType; @@ -228,8 +226,10 @@ public class MappedFieldType extends FieldType { /** * Checks for any conflicts between this field type and other. + * If strict is true, all properties must be equal. + * Otherwise, only properties which must never change in an index are checked. */ - public void checkCompatibility(MappedFieldType other, List conflicts) { + public void checkCompatibility(MappedFieldType other, List conflicts, boolean strict) { boolean indexed = indexOptions() != IndexOptions.NONE; boolean mergeWithIndexed = other.indexOptions() != IndexOptions.NONE; // TODO: should be validating if index options go "up" (but "down" is ok) @@ -277,10 +277,30 @@ public class MappedFieldType extends FieldType { if (!names().equals(other.names())) { conflicts.add("mapper [" + names().fullName() + "] has different index_name"); } - if (Objects.equals(similarity(), other.similarity()) == false) { conflicts.add("mapper [" + names().fullName() + "] has different similarity"); } + + if (strict) { + if (omitNorms() != other.omitNorms()) { + conflicts.add("mapper [" + names().fullName() + "] is used by multiple types. Set update_all_types to true to update [omit_norms] across all types."); + } + if (boost() != other.boost()) { + conflicts.add("mapper [" + names().fullName() + "] is used by multiple types. Set update_all_types to true to update [boost] across all types."); + } + if (normsLoading() != other.normsLoading()) { + conflicts.add("mapper [" + names().fullName() + "] is used by multiple types. Set update_all_types to true to update [norms].loading across all types."); + } + if (Objects.equals(searchAnalyzer(), other.searchAnalyzer()) == false) { + conflicts.add("mapper [" + names().fullName() + "] is used by multiple types. Set update_all_types to true to update [search_analyzer] across all types."); + } + if (Objects.equals(fieldDataType(), other.fieldDataType()) == false) { + conflicts.add("mapper [" + names().fullName() + "] is used by multiple types. Set update_all_types to true to update [fielddata] across all types."); + } + if (Objects.equals(nullValue(), other.nullValue()) == false) { + conflicts.add("mapper [" + names().fullName() + "] is used by multiple types. Set update_all_types to true to update [null_value] across all types."); + } + } } public boolean isNumeric() { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldTypeReference.java b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldTypeReference.java new file mode 100644 index 00000000000..8153f004cee --- /dev/null +++ b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldTypeReference.java @@ -0,0 +1,50 @@ +/* + * 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 + private int refCount; + + public MappedFieldTypeReference(MappedFieldType fieldType) { + fieldType.freeze(); // ensure frozen + this.fieldType = fieldType; + this.refCount = 1; + } + + public MappedFieldType get() { + return fieldType; + } + + public void set(MappedFieldType fieldType) { + fieldType.freeze(); // ensure frozen + this.fieldType = fieldType; + } + + public int getRefCount() { + return refCount; + } + + public void incRefCount() { + ++refCount; + } +} 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 016868e7022..55253783909 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/Mapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/Mapper.java @@ -86,14 +86,18 @@ public interface Mapper extends ToXContent, Iterable { private final SimilarityLookupService similarityLookupService; + private final MapperService mapperService; + private final ImmutableMap typeParsers; private final Version indexVersionCreated; public ParserContext(AnalysisService analysisService, SimilarityLookupService similarityLookupService, + MapperService mapperService, ImmutableMap typeParsers, Version indexVersionCreated) { this.analysisService = analysisService; this.similarityLookupService = similarityLookupService; + this.mapperService = mapperService; this.typeParsers = typeParsers; this.indexVersionCreated = indexVersionCreated; } @@ -106,6 +110,10 @@ public interface Mapper extends ToXContent, Iterable { return similarityLookupService; } + public MapperService mapperService() { + return mapperService; + } + public TypeParser typeParser(String type) { return typeParsers.get(Strings.toUnderscoreCase(type)); } 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 51845fdf838..4e919a59433 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/MapperBuilders.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MapperBuilders.java @@ -37,48 +37,48 @@ public final class MapperBuilders { } - public static DocumentMapper.Builder doc(String index, Settings settings, RootObjectMapper.Builder objectBuilder) { - return new DocumentMapper.Builder(index, settings, objectBuilder); + public static DocumentMapper.Builder doc(String index, Settings settings, RootObjectMapper.Builder objectBuilder, MapperService mapperService) { + return new DocumentMapper.Builder(index, settings, objectBuilder, mapperService); } public static SourceFieldMapper.Builder source() { return new SourceFieldMapper.Builder(); } - public static IdFieldMapper.Builder id() { - return new IdFieldMapper.Builder(); + public static IdFieldMapper.Builder id(MappedFieldType existing) { + return new IdFieldMapper.Builder(existing); } - public static RoutingFieldMapper.Builder routing() { - return new RoutingFieldMapper.Builder(); + public static RoutingFieldMapper.Builder routing(MappedFieldType existing) { + return new RoutingFieldMapper.Builder(existing); } - public static UidFieldMapper.Builder uid() { - return new UidFieldMapper.Builder(); + public static UidFieldMapper.Builder uid(MappedFieldType existing) { + return new UidFieldMapper.Builder(existing); } - public static SizeFieldMapper.Builder size() { - return new SizeFieldMapper.Builder(); + public static SizeFieldMapper.Builder size(MappedFieldType existing) { + return new SizeFieldMapper.Builder(existing); } public static VersionFieldMapper.Builder version() { return new VersionFieldMapper.Builder(); } - public static TypeFieldMapper.Builder type() { - return new TypeFieldMapper.Builder(); + public static TypeFieldMapper.Builder type(MappedFieldType existing) { + return new TypeFieldMapper.Builder(existing); } public static FieldNamesFieldMapper.Builder fieldNames() { return new FieldNamesFieldMapper.Builder(); } - public static IndexFieldMapper.Builder index() { - return new IndexFieldMapper.Builder(); + public static IndexFieldMapper.Builder index(MappedFieldType existing) { + return new IndexFieldMapper.Builder(existing); } - public static TimestampFieldMapper.Builder timestamp() { - return new TimestampFieldMapper.Builder(); + public static TimestampFieldMapper.Builder timestamp(MappedFieldType existing) { + return new TimestampFieldMapper.Builder(existing); } public static TTLFieldMapper.Builder ttl() { @@ -89,8 +89,8 @@ public final class MapperBuilders { return new ParentFieldMapper.Builder(); } - public static AllFieldMapper.Builder all() { - return new AllFieldMapper.Builder(); + public static AllFieldMapper.Builder all(MappedFieldType existing) { + return new AllFieldMapper.Builder(existing); } 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 eb36fa88a41..e7d275f4c70 100755 --- a/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java @@ -21,7 +21,10 @@ package org.elasticsearch.index.mapper; import com.carrotsearch.hppc.ObjectHashSet; import com.google.common.base.Predicate; -import com.google.common.collect.*; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterators; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.DelegatingAnalyzerWrapper; @@ -36,7 +39,6 @@ import org.apache.lucene.search.ConstantScoreQuery; import org.apache.lucene.search.TermQuery; import org.apache.lucene.util.BytesRef; import org.elasticsearch.ElasticsearchGenerationException; -import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.Version; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.collect.ImmutableOpenMap; @@ -102,8 +104,8 @@ public class MapperService extends AbstractIndexComponent { final ReentrantReadWriteLock mappingLock = new ReentrantReadWriteLock(); private final ReleasableLock mappingWriteLock = new ReleasableLock(mappingLock.writeLock()); - private volatile FieldMappersLookup fieldMappers; - private volatile ImmutableOpenMap fullPathObjectMappers = ImmutableOpenMap.of(); + private volatile FieldTypeLookup fieldTypes; + private volatile ImmutableOpenMap fullPathObjectMappers = ImmutableOpenMap.of(); private boolean hasNested = false; // updated dynamically to true when a nested object is added private final DocumentMapperParser documentParser; @@ -124,7 +126,7 @@ public class MapperService extends AbstractIndexComponent { super(index, indexSettings); this.analysisService = analysisService; this.fieldDataService = fieldDataService; - this.fieldMappers = new FieldMappersLookup(); + this.fieldTypes = new FieldTypeLookup(); this.documentParser = new DocumentMapperParser(index, indexSettings, this, analysisService, similarityLookupService, scriptService); this.searchAnalyzer = new SmartIndexNameSearchAnalyzer(analysisService.defaultSearchAnalyzer()); this.searchQuoteAnalyzer = new SmartIndexNameSearchQuoteAnalyzer(analysisService.defaultSearchQuoteAnalyzer()); @@ -214,7 +216,7 @@ public class MapperService extends AbstractIndexComponent { typeListeners.remove(listener); } - public DocumentMapper merge(String type, CompressedXContent mappingSource, boolean applyDefault) { + public DocumentMapper merge(String type, CompressedXContent mappingSource, boolean applyDefault, boolean updateAllTypes) { if (DEFAULT_MAPPING.equals(type)) { // verify we can parse it DocumentMapper mapper = documentParser.parseCompressed(type, mappingSource); @@ -230,13 +232,13 @@ public class MapperService extends AbstractIndexComponent { } return mapper; } else { - return merge(parse(type, mappingSource, applyDefault)); + return merge(parse(type, mappingSource, applyDefault), updateAllTypes); } } // 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) { + private DocumentMapper merge(DocumentMapper mapper, boolean updateAllTypes) { try (ReleasableLock lock = mappingWriteLock.acquire()) { if (mapper.type().length() == 0) { throw new InvalidTypeNameException("mapping type name is empty"); @@ -262,7 +264,7 @@ public class MapperService extends AbstractIndexComponent { DocumentMapper oldMapper = mappers.get(mapper.type()); if (oldMapper != null) { - MergeResult result = oldMapper.merge(mapper.mapping(), false); + MergeResult result = oldMapper.merge(mapper.mapping(), false, updateAllTypes); if (result.hasConflicts()) { // TODO: What should we do??? if (logger.isDebugEnabled()) { @@ -270,19 +272,18 @@ public class MapperService extends AbstractIndexComponent { } } fieldDataService.onMappingUpdate(); - assert assertSerialization(oldMapper); return oldMapper; } else { List newObjectMappers = new ArrayList<>(); List newFieldMappers = new ArrayList<>(); for (RootMapper rootMapper : mapper.mapping().rootMappers) { if (rootMapper instanceof FieldMapper) { - newFieldMappers.add((FieldMapper)rootMapper); + newFieldMappers.add((FieldMapper) rootMapper); } } MapperUtils.collect(mapper.mapping().root, newObjectMappers, newFieldMappers); - addFieldMappers(newFieldMappers); - addObjectMappers(newObjectMappers); + checkNewMappersCompatibility(newObjectMappers, newFieldMappers, updateAllTypes); + addMappers(newObjectMappers, newFieldMappers); for (DocumentTypeListener typeListener : typeListeners) { typeListener.beforeCreate(mapper); @@ -313,28 +314,33 @@ public class MapperService extends AbstractIndexComponent { return true; } - protected void addObjectMappers(Collection objectMappers) { + protected void checkNewMappersCompatibility(Collection newObjectMappers, Collection newFieldMappers, boolean updateAllTypes) { assert mappingLock.isWriteLockedByCurrentThread(); - ImmutableOpenMap.Builder fullPathObjectMappers = ImmutableOpenMap.builder(this.fullPathObjectMappers); - for (ObjectMapper objectMapper : objectMappers) { - ObjectMappers mappers = fullPathObjectMappers.get(objectMapper.fullPath()); - if (mappers == null) { - mappers = new ObjectMappers(objectMapper); - } else { - mappers = mappers.concat(objectMapper); + for (ObjectMapper newObjectMapper : newObjectMappers) { + ObjectMapper existingObjectMapper = fullPathObjectMappers.get(newObjectMapper.fullPath()); + if (existingObjectMapper != null) { + MergeResult result = new MergeResult(true, updateAllTypes); + existingObjectMapper.merge(newObjectMapper, result); + if (result.hasConflicts()) { + throw new IllegalArgumentException("Mapper for [" + newObjectMapper.fullPath() + "] conflicts with existing mapping in other types" + + Arrays.toString(result.buildConflicts())); + } } - fullPathObjectMappers.put(objectMapper.fullPath(), mappers); - // update the hasNested flag + } + fieldTypes.checkCompatibility(newFieldMappers, updateAllTypes); + } + + protected void addMappers(Collection objectMappers, Collection fieldMappers) { + assert mappingLock.isWriteLockedByCurrentThread(); + ImmutableOpenMap.Builder fullPathObjectMappers = ImmutableOpenMap.builder(this.fullPathObjectMappers); + for (ObjectMapper objectMapper : objectMappers) { + fullPathObjectMappers.put(objectMapper.fullPath(), objectMapper); if (objectMapper.nested().isNested()) { hasNested = true; } } this.fullPathObjectMappers = fullPathObjectMappers.build(); - } - - protected void addFieldMappers(Collection fieldMappers) { - assert mappingLock.isWriteLockedByCurrentThread(); - this.fieldMappers = this.fieldMappers.copyAndAddAll(fieldMappers); + this.fieldTypes = this.fieldTypes.copyAndAddAll(fieldMappers); } public DocumentMapper parse(String mappingType, CompressedXContent mappingSource, boolean applyDefault) throws MapperParsingException { @@ -479,11 +485,7 @@ public class MapperService extends AbstractIndexComponent { * If multiple types have fields with the same index name, the first is returned. */ public MappedFieldType indexName(String indexName) { - FieldMappers mappers = fieldMappers.indexName(indexName); - if (mappers == null) { - return null; - } - return mappers.mapper().fieldType(); + return fieldTypes.getByIndexName(indexName); } /** @@ -492,11 +494,7 @@ public class MapperService extends AbstractIndexComponent { * If multiple types have fields with the same full name, the first is returned. */ public MappedFieldType fullName(String fullName) { - FieldMappers mappers = fieldMappers.fullName(fullName); - if (mappers == null) { - return null; - } - return mappers.mapper().fieldType(); + return fieldTypes.get(fullName); } /** @@ -504,52 +502,21 @@ public class MapperService extends AbstractIndexComponent { * then the fields will be returned with a type prefix. */ public Collection simpleMatchToIndexNames(String pattern) { - return simpleMatchToIndexNames(pattern, null); - } - /** - * Returns all the fields that match the given pattern, with an optional narrowing - * based on a list of types. - */ - public Collection simpleMatchToIndexNames(String pattern, @Nullable String[] types) { if (Regex.isSimpleMatchPattern(pattern) == false) { // no wildcards return ImmutableList.of(pattern); } - - if (MetaData.isAllTypes(types)) { - return fieldMappers.simpleMatchToIndexNames(pattern); - } - - List fields = Lists.newArrayList(); - for (String type : types) { - DocumentMapper possibleDocMapper = mappers.get(type); - if (possibleDocMapper != null) { - for (String indexName : possibleDocMapper.mappers().simpleMatchToIndexNames(pattern)) { - fields.add(indexName); - } - } - } - return fields; + return fieldTypes.simpleMatchToIndexNames(pattern); } + // TODO: remove this since the underlying index names are now the same across all types + public Collection simpleMatchToIndexNames(String pattern, @Nullable String[] types) { + return simpleMatchToIndexNames(pattern); + } + + // TODO: remove types param, since the object mapper must be the same across all types public ObjectMapper getObjectMapper(String name, @Nullable String[] types) { - if (types == null || types.length == 0 || types.length == 1 && types[0].equals("_all")) { - ObjectMappers mappers = fullPathObjectMappers.get(name); - if (mappers != null) { - return mappers.mapper(); - } - return null; - } - for (String type : types) { - DocumentMapper possibleDocMapper = mappers.get(type); - if (possibleDocMapper != null) { - ObjectMapper mapper = possibleDocMapper.objectMappers().get(name); - if (mapper != null) { - return mapper; - } - } - } - return null; + return fullPathObjectMappers.get(name); } public MappedFieldType smartNameFieldType(String smartName) { @@ -560,22 +527,9 @@ public class MapperService extends AbstractIndexComponent { return indexName(smartName); } + // TODO: remove this since the underlying index names are now the same across all types public MappedFieldType smartNameFieldType(String smartName, @Nullable String[] types) { - if (types == null || types.length == 0 || types.length == 1 && types[0].equals("_all")) { - return smartNameFieldType(smartName); - } - for (String type : types) { - DocumentMapper documentMapper = mappers.get(type); - // we found a mapper - if (documentMapper != null) { - // see if we find a field for it - FieldMappers mappers = documentMapper.mappers().smartName(smartName); - if (mappers != null) { - return mappers.mapper().fieldType(); - } - } - } - return null; + return smartNameFieldType(smartName); } /** @@ -622,18 +576,14 @@ public class MapperService extends AbstractIndexComponent { } else { do { String objectPath = fieldName.substring(0, indexOf); - ObjectMappers objectMappers = fullPathObjectMappers.get(objectPath); - if (objectMappers == null) { + ObjectMapper objectMapper = fullPathObjectMappers.get(objectPath); + if (objectMapper == null) { indexOf = objectPath.lastIndexOf('.'); continue; } - if (objectMappers.hasNested()) { - for (ObjectMapper objectMapper : objectMappers) { - if (objectMapper.nested().isNested()) { - return objectMapper; - } - } + if (objectMapper.nested().isNested()) { + return objectMapper; } indexOf = objectPath.lastIndexOf('.'); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MapperUtils.java b/core/src/main/java/org/elasticsearch/index/mapper/MapperUtils.java index 6ea2245e066..d46c32a932b 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/MapperUtils.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MapperUtils.java @@ -19,28 +19,16 @@ package org.elasticsearch.index.mapper; -import org.elasticsearch.common.Strings; import org.elasticsearch.index.mapper.object.ObjectMapper; import org.elasticsearch.index.mapper.object.RootObjectMapper; -import java.io.IOException; import java.util.Collection; public enum MapperUtils { ; private static MergeResult newStrictMergeResult() { - return new MergeResult(false) { - - @Override - public boolean hasConflicts() { - return false; - } - - @Override - public String[] buildConflicts() { - return Strings.EMPTY_ARRAY; - } + return new MergeResult(false, false) { @Override public void addFieldMappers(Collection fieldMappers) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MergeResult.java b/core/src/main/java/org/elasticsearch/index/mapper/MergeResult.java index af7bac84649..f5698a0ed18 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/MergeResult.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MergeResult.java @@ -19,6 +19,7 @@ package org.elasticsearch.index.mapper; +import org.elasticsearch.common.Strings; import org.elasticsearch.index.mapper.object.ObjectMapper; import java.util.ArrayList; @@ -26,29 +27,55 @@ import java.util.Collection; import java.util.List; /** A container for tracking results of a mapping merge. */ -public abstract class MergeResult { +public class MergeResult { private final boolean simulate; + private final boolean updateAllTypes; - public MergeResult(boolean simulate) { + private final List conflicts = new ArrayList<>(); + private final List newFieldMappers = new ArrayList<>(); + private final List newObjectMappers = new ArrayList<>(); + + public MergeResult(boolean simulate, boolean updateAllTypes) { this.simulate = simulate; + this.updateAllTypes = updateAllTypes; } - public abstract void addFieldMappers(Collection fieldMappers); + public void addFieldMappers(Collection fieldMappers) { + assert simulate() == false; + newFieldMappers.addAll(fieldMappers); + } - public abstract void addObjectMappers(Collection objectMappers); + public void addObjectMappers(Collection objectMappers) { + assert simulate() == false; + newObjectMappers.addAll(objectMappers); + } - public abstract Collection getNewFieldMappers(); + public Collection getNewFieldMappers() { + return newFieldMappers; + } - public abstract Collection getNewObjectMappers(); + public Collection getNewObjectMappers() { + return newObjectMappers; + } public boolean simulate() { return simulate; } - public abstract void addConflict(String mergeFailure); + public boolean updateAllTypes() { + return updateAllTypes; + } - public abstract boolean hasConflicts(); + public void addConflict(String mergeFailure) { + conflicts.add(mergeFailure); + } - public abstract String[] buildConflicts(); -} + public boolean hasConflicts() { + return conflicts.isEmpty() == false; + } + + public String[] buildConflicts() { + return conflicts.toArray(Strings.EMPTY_ARRAY); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/elasticsearch/index/mapper/ParseContext.java b/core/src/main/java/org/elasticsearch/index/mapper/ParseContext.java index b99caf85dc3..2af7b2a687c 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/ParseContext.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/ParseContext.java @@ -280,6 +280,11 @@ public abstract class ParseContext { return in.analysisService(); } + @Override + public MapperService mapperService() { + return in.mapperService(); + } + @Override public String id() { return in.id(); @@ -513,6 +518,11 @@ public abstract class ParseContext { return docMapperParser.analysisService; } + @Override + public MapperService mapperService() { + return docMapperParser.mapperService; + } + @Override public String id() { return id; @@ -701,6 +711,8 @@ public abstract class ParseContext { public abstract AnalysisService analysisService(); + public abstract MapperService mapperService(); + public abstract String id(); public abstract void ignoredValue(String indexName, String value); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java index d69aabe4f5c..fe24c10b4af 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java @@ -22,7 +22,6 @@ package org.elasticsearch.index.mapper.core; import com.carrotsearch.hppc.cursors.ObjectCursor; import com.carrotsearch.hppc.cursors.ObjectObjectCursor; import com.google.common.base.Function; -import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterators; import org.apache.lucene.document.Field; @@ -39,6 +38,7 @@ import org.elasticsearch.index.fielddata.FieldDataType; import org.elasticsearch.index.mapper.ContentPath; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.MappedFieldType; +import org.elasticsearch.index.mapper.MappedFieldTypeReference; import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.index.mapper.MapperParsingException; import org.elasticsearch.index.mapper.MergeMappingException; @@ -133,7 +133,7 @@ public abstract class AbstractFieldMapper implements FieldMapper { } public T storeTermVectors(boolean termVectors) { - if (termVectors) { + if (termVectors != this.fieldType.storeTermVectors()) { this.fieldType.setStoreTermVectors(termVectors); } // don't set it to false, it is default and might be flipped by a more specific option return builder; @@ -268,7 +268,7 @@ public abstract class AbstractFieldMapper implements FieldMapper { } } - protected MappedFieldType fieldType; + protected MappedFieldTypeReference fieldTypeRef; protected final boolean hasDefaultDocValues; protected Settings customFieldDataSettings; protected final MultiFields multiFields; @@ -302,14 +302,16 @@ public abstract class AbstractFieldMapper implements FieldMapper { } hasDefaultDocValues = docValues == null; - this.fieldType = fieldType.clone(); + this.fieldTypeRef = new MappedFieldTypeReference(fieldType); // must init first so defaultDocValues() can be called + fieldType = fieldType.clone(); if (fieldType.indexAnalyzer() == null && fieldType.tokenized() == false && fieldType.indexOptions() != IndexOptions.NONE) { - this.fieldType().setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); - this.fieldType().setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); + fieldType.setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); + fieldType.setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); } - this.fieldType().setHasDocValues(docValues == null ? defaultDocValues() : docValues); - this.fieldType().setFieldDataType(fieldDataType); - this.fieldType().freeze(); + fieldType.setHasDocValues(docValues == null ? defaultDocValues() : docValues); + fieldType.setFieldDataType(fieldDataType); + fieldType.freeze(); + this.fieldTypeRef.set(fieldType); // now reset ref once extra settings have been initialized this.multiFields = multiFields; this.copyTo = copyTo; @@ -335,7 +337,21 @@ public abstract class AbstractFieldMapper implements FieldMapper { @Override public MappedFieldType fieldType() { - return fieldType; + return fieldTypeRef.get(); + } + + @Override + public MappedFieldTypeReference fieldTypeReference() { + return fieldTypeRef; + } + + @Override + public void setFieldTypeReference(MappedFieldTypeReference ref) { + if (ref.get().equals(fieldType()) == false) { + throw new IllegalStateException("Cannot overwrite field type reference to unequal reference"); + } + ref.incRefCount(); + this.fieldTypeRef = ref; } @Override @@ -393,7 +409,8 @@ public abstract class AbstractFieldMapper implements FieldMapper { } AbstractFieldMapper fieldMergeWith = (AbstractFieldMapper) mergeWith; List subConflicts = new ArrayList<>(); // TODO: just expose list from MergeResult? - fieldType().checkCompatibility(fieldMergeWith.fieldType(), subConflicts); + boolean strict = this.fieldTypeRef.getRefCount() > 1 && mergeResult.updateAllTypes() == false; + fieldType().checkCompatibility(fieldMergeWith.fieldType(), subConflicts, strict); for (String conflict : subConflicts) { mergeResult.addConflict(conflict); } @@ -401,13 +418,10 @@ public abstract class AbstractFieldMapper implements FieldMapper { if (mergeResult.simulate() == false && mergeResult.hasConflicts() == false) { // apply changeable values - this.fieldType = fieldMergeWith.fieldType().clone(); - this.fieldType().freeze(); - if (fieldMergeWith.customFieldDataSettings != null) { - if (!Objects.equal(fieldMergeWith.customFieldDataSettings, this.customFieldDataSettings)) { - this.customFieldDataSettings = fieldMergeWith.customFieldDataSettings; - } - } + MappedFieldType fieldType = fieldMergeWith.fieldType().clone(); + fieldType.freeze(); + fieldTypeRef.set(fieldType); + this.customFieldDataSettings = fieldMergeWith.customFieldDataSettings; this.copyTo = fieldMergeWith.copyTo; } } @@ -468,7 +482,8 @@ public abstract class AbstractFieldMapper implements FieldMapper { } TreeMap orderedFielddataSettings = new TreeMap<>(); - if (customFieldDataSettings != null) { + boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; + if (hasCustomFieldDataSettings) { orderedFielddataSettings.putAll(customFieldDataSettings.getAsMap()); builder.field("fielddata", orderedFielddataSettings); } else if (includeDefaults) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/CompletionFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/CompletionFieldMapper.java index b9f92895943..ca9dbb28d96 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/CompletionFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/CompletionFieldMapper.java @@ -243,8 +243,8 @@ public class CompletionFieldMapper extends AbstractFieldMapper { } @Override - public void checkCompatibility(MappedFieldType fieldType, List conflicts) { - super.checkCompatibility(fieldType, conflicts); + public void checkCompatibility(MappedFieldType fieldType, List conflicts, boolean strict) { + super.checkCompatibility(fieldType, conflicts, strict); CompletionFieldType other = (CompletionFieldType)fieldType; if (analyzingSuggestLookupProvider.hasPayloads() != other.analyzingSuggestLookupProvider.hasPayloads()) { conflicts.add("mapper [" + names().fullName() + "] has different payload values"); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java index 2238a921909..74ecffa6df9 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java @@ -239,6 +239,7 @@ public class DateFieldMapper extends NumberFieldMapper { if (!super.equals(o)) return false; DateFieldType that = (DateFieldType) o; return Objects.equals(dateTimeFormatter.format(), that.dateTimeFormatter.format()) && + Objects.equals(dateTimeFormatter.locale(), that.dateTimeFormatter.locale()) && Objects.equals(timeUnit, that.timeUnit); } @@ -247,6 +248,23 @@ public class DateFieldMapper extends NumberFieldMapper { return Objects.hash(super.hashCode(), dateTimeFormatter.format(), timeUnit); } + @Override + public void checkCompatibility(MappedFieldType fieldType, List conflicts, boolean strict) { + super.checkCompatibility(fieldType, conflicts, strict); + if (strict) { + DateFieldType other = (DateFieldType)fieldType; + if (Objects.equals(dateTimeFormatter().format(), other.dateTimeFormatter().format()) == false) { + conflicts.add("mapper [" + names().fullName() + "] is used by multiple types. Set update_all_types to true to update [format] across all types."); + } + if (Objects.equals(dateTimeFormatter().locale(), other.dateTimeFormatter().locale()) == false) { + conflicts.add("mapper [" + names().fullName() + "] is used by multiple types. Set update_all_types to true to update [locale] across all types."); + } + if (Objects.equals(timeUnit(), other.timeUnit()) == false) { + conflicts.add("mapper [" + names().fullName() + "] is used by multiple types. Set update_all_types to true to update [numeric_resolution] across all types."); + } + } + } + public FormatDateTimeFormatter dateTimeFormatter() { return dateTimeFormatter; } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java index 034abb34951..a9ebe135330 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java @@ -317,8 +317,14 @@ public abstract class NumberFieldMapper extends AbstractFieldMapper implements A if (!this.getClass().equals(mergeWith.getClass())) { return; } - if (!mergeResult.simulate()) { - NumberFieldMapper nfmMergeWith = (NumberFieldMapper) mergeWith; + NumberFieldMapper nfmMergeWith = (NumberFieldMapper) mergeWith; + if (this.fieldTypeRef.getRefCount() > 1 && mergeResult.updateAllTypes() == false) { + if (fieldType().numericPrecisionStep() != nfmMergeWith.fieldType().numericPrecisionStep()) { + mergeResult.addConflict("mapper [" + fieldType().names().fullName() + "] is used by multiple types. Set update_all_types to true to update precision_step across all types."); + } + } + + if (mergeResult.simulate() == false && mergeResult.hasConflicts() == false) { this.includeInAll = nfmMergeWith.includeInAll; if (nfmMergeWith.ignoreMalformed.explicit()) { this.ignoreMalformed = nfmMergeWith.ignoreMalformed; diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/TypeParsers.java b/core/src/main/java/org/elasticsearch/index/mapper/core/TypeParsers.java index d7434a574dd..1c3d5f9b0bd 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/TypeParsers.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/TypeParsers.java @@ -182,8 +182,8 @@ public class TypeParsers { } public static void parseField(AbstractFieldMapper.Builder builder, String name, Map fieldNode, Mapper.TypeParser.ParserContext parserContext) { - NamedAnalyzer indexAnalyzer = null; - NamedAnalyzer searchAnalyzer = null; + NamedAnalyzer indexAnalyzer = builder.fieldType.indexAnalyzer(); + NamedAnalyzer searchAnalyzer = builder.fieldType.searchAnalyzer(); for (Iterator> iterator = fieldNode.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = iterator.next(); final String propName = Strings.toUnderscoreCase(entry.getKey()); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoPointFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoPointFieldMapper.java index 33cc4f460b4..85a8a9f78d2 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoPointFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoPointFieldMapper.java @@ -330,8 +330,8 @@ public class GeoPointFieldMapper extends AbstractFieldMapper implements ArrayVal } @Override - public void checkCompatibility(MappedFieldType fieldType, List conflicts) { - super.checkCompatibility(fieldType, conflicts); + public void checkCompatibility(MappedFieldType fieldType, List conflicts, boolean strict) { + super.checkCompatibility(fieldType, conflicts, strict); GeoPointFieldType other = (GeoPointFieldType)fieldType; if (isLatLonEnabled() != other.isLatLonEnabled()) { conflicts.add("mapper [" + names().fullName() + "] has different lat_lon"); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapper.java index bafa84d9285..f83d0575f34 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapper.java @@ -199,7 +199,7 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper { } @Override - public MappedFieldType clone() { + public GeoShapeFieldType clone() { return new GeoShapeFieldType(this); } @@ -246,8 +246,8 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper { } @Override - public void checkCompatibility(MappedFieldType fieldType, List conflicts) { - super.checkCompatibility(fieldType, conflicts); + public void checkCompatibility(MappedFieldType fieldType, List conflicts, boolean strict) { + super.checkCompatibility(fieldType, conflicts, strict); GeoShapeFieldType other = (GeoShapeFieldType)fieldType; // prevent user from changing strategies if (strategyName().equals(other.strategyName()) == false) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java index 9234a84f1fc..10646d596b3 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java @@ -92,8 +92,8 @@ public class AllFieldMapper extends AbstractFieldMapper implements RootMapper { private EnabledAttributeMapper enabled = Defaults.ENABLED; - public Builder() { - super(Defaults.NAME, Defaults.FIELD_TYPE); + public Builder(MappedFieldType existing) { + super(Defaults.NAME, existing == null ? Defaults.FIELD_TYPE : existing); builder = this; indexName = Defaults.INDEX_NAME; } @@ -119,7 +119,7 @@ public class AllFieldMapper extends AbstractFieldMapper implements RootMapper { public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - AllFieldMapper.Builder builder = all(); + AllFieldMapper.Builder builder = all(parserContext.mapperService().fullName(NAME)); // parseField below will happily parse the doc_values setting, but it is then never passed to // the AllFieldMapper ctor in the builder since it is not valid. Here we validate @@ -191,8 +191,11 @@ public class AllFieldMapper extends AbstractFieldMapper implements RootMapper { private EnabledAttributeMapper enabledState; - public AllFieldMapper(Settings indexSettings) { - this(Defaults.FIELD_TYPE.clone(), Defaults.ENABLED, null, indexSettings); + public AllFieldMapper(Settings indexSettings, MappedFieldType existing) { + this(existing == null ? Defaults.FIELD_TYPE.clone() : existing.clone(), + Defaults.ENABLED, + existing == null ? null : (existing.fieldDataType() == null ? null : existing.fieldDataType().getSettings()), + indexSettings); } protected AllFieldMapper(MappedFieldType fieldType, EnabledAttributeMapper enabled, @@ -312,7 +315,8 @@ public class AllFieldMapper extends AbstractFieldMapper implements RootMapper { builder.field("similarity", SimilarityLookupService.DEFAULT_SIMILARITY); } - if (customFieldDataSettings != null) { + boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; + if (hasCustomFieldDataSettings) { builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); } else if (includeDefaults) { builder.field("fielddata", (Map) fieldType().fieldDataType().getSettings().getAsMap()); 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 65c867bec95..780d36abade 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 @@ -159,6 +159,16 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper implements RootMa return Objects.hash(super.hashCode(), enabled); } + @Override + public void checkCompatibility(MappedFieldType fieldType, List conflicts, boolean strict) { + if (strict) { + FieldNamesFieldType other = (FieldNamesFieldType)fieldType; + if (isEnabled() != other.isEnabled()) { + conflicts.add("mapper [" + names().fullName() + "] is used by multiple types. Set update_all_types to true to update [enabled] across all types."); + } + } + } + public void setEnabled(boolean enabled) { checkIfFrozen(); this.enabled = enabled; @@ -190,8 +200,10 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper implements RootMa private final MappedFieldType defaultFieldType; private final boolean pre13Index; // if the index was created before 1.3, _field_names is always disabled - public FieldNamesFieldMapper(Settings indexSettings) { - this(Defaults.FIELD_TYPE.clone(), null, indexSettings); + public FieldNamesFieldMapper(Settings indexSettings, MappedFieldType existing) { + this(existing == null ? Defaults.FIELD_TYPE.clone() : existing.clone(), + existing == null ? null : (existing.fieldDataType() == null ? null : existing.fieldDataType().getSettings()), + indexSettings); } public FieldNamesFieldMapper(MappedFieldType fieldType, @Nullable Settings fieldDataSettings, Settings indexSettings) { @@ -199,9 +211,10 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper implements RootMa this.defaultFieldType = Defaults.FIELD_TYPE; this.pre13Index = Version.indexCreated(indexSettings).before(Version.V_1_3_0); if (this.pre13Index) { - this.fieldType = fieldType().clone(); - fieldType().setEnabled(false); - fieldType().freeze(); + FieldNamesFieldType newFieldType = fieldType().clone(); + newFieldType.setEnabled(false); + newFieldType.freeze(); + fieldTypeRef.set(newFieldType); } } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java index 40d3e0f314a..65e0d1ef4ed 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java @@ -92,8 +92,8 @@ public class IdFieldMapper extends AbstractFieldMapper implements RootMapper { private String path = Defaults.PATH; - public Builder() { - super(Defaults.NAME, Defaults.FIELD_TYPE); + public Builder(MappedFieldType existing) { + super(Defaults.NAME, existing == null ? Defaults.FIELD_TYPE : existing); indexName = Defaults.NAME; } @@ -120,7 +120,7 @@ public class IdFieldMapper extends AbstractFieldMapper implements RootMapper { if (parserContext.indexVersionCreated().onOrAfter(Version.V_2_0_0)) { throw new MapperParsingException(NAME + " is not configurable"); } - IdFieldMapper.Builder builder = id(); + IdFieldMapper.Builder builder = id(parserContext.mapperService().fullName(NAME)); parseField(builder, builder.name, node, parserContext); for (Iterator> iterator = node.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = iterator.next(); @@ -226,8 +226,10 @@ public class IdFieldMapper extends AbstractFieldMapper implements RootMapper { private final String path; - public IdFieldMapper(Settings indexSettings) { - this(idFieldType(indexSettings), null, Defaults.PATH, null, indexSettings); + public IdFieldMapper(Settings indexSettings, MappedFieldType existing) { + this(idFieldType(indexSettings, existing), null, Defaults.PATH, + existing == null ? null : (existing.fieldDataType() == null ? null : existing.fieldDataType().getSettings()), + indexSettings); } protected IdFieldMapper(MappedFieldType fieldType, Boolean docValues, String path, @@ -236,7 +238,10 @@ public class IdFieldMapper extends AbstractFieldMapper implements RootMapper { this.path = path; } - private static MappedFieldType idFieldType(Settings indexSettings) { + private static MappedFieldType idFieldType(Settings indexSettings, MappedFieldType existing) { + if (existing != null) { + return existing.clone(); + } MappedFieldType fieldType = Defaults.FIELD_TYPE.clone(); boolean pre2x = Version.indexCreated(indexSettings).before(Version.V_2_0_0); if (pre2x && indexSettings.getAsBoolean("index.mapping._id.indexed", true) == false) { @@ -306,12 +311,13 @@ public class IdFieldMapper extends AbstractFieldMapper implements RootMapper { return builder; } boolean includeDefaults = params.paramAsBoolean("include_defaults", false); + boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; // if all are defaults, no sense to write it at all if (!includeDefaults && fieldType().stored() == Defaults.FIELD_TYPE.stored() && fieldType().indexOptions() == Defaults.FIELD_TYPE.indexOptions() && path == Defaults.PATH - && customFieldDataSettings == null) { + && hasCustomFieldDataSettings == false) { return builder; } builder.startObject(CONTENT_TYPE); @@ -325,7 +331,7 @@ public class IdFieldMapper extends AbstractFieldMapper implements RootMapper { builder.field("path", path); } - if (customFieldDataSettings != null) { + if (hasCustomFieldDataSettings) { builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); } else if (includeDefaults) { builder.field("fielddata", (Map) fieldType().fieldDataType().getSettings().getAsMap()); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java index 689cd344014..7035a6f2858 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java @@ -79,8 +79,8 @@ public class IndexFieldMapper extends AbstractFieldMapper implements RootMapper private EnabledAttributeMapper enabledState = EnabledAttributeMapper.UNSET_DISABLED; - public Builder() { - super(Defaults.NAME, Defaults.FIELD_TYPE); + public Builder(MappedFieldType existing) { + super(Defaults.NAME, existing == null ? Defaults.FIELD_TYPE : existing); indexName = Defaults.NAME; } @@ -99,7 +99,7 @@ public class IndexFieldMapper extends AbstractFieldMapper implements RootMapper public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - IndexFieldMapper.Builder builder = MapperBuilders.index(); + IndexFieldMapper.Builder builder = MapperBuilders.index(parserContext.mapperService().fullName(NAME)); if (parserContext.indexVersionCreated().before(Version.V_2_0_0)) { parseField(builder, builder.name, node, parserContext); } @@ -144,8 +144,10 @@ public class IndexFieldMapper extends AbstractFieldMapper implements RootMapper private EnabledAttributeMapper enabledState; - public IndexFieldMapper(Settings indexSettings) { - this(Defaults.FIELD_TYPE.clone(), Defaults.ENABLED_STATE, null, indexSettings); + public IndexFieldMapper(Settings indexSettings, MappedFieldType existing) { + this(existing == null ? Defaults.FIELD_TYPE.clone() : existing, + Defaults.ENABLED_STATE, + existing == null ? null : (existing.fieldDataType() == null ? null : existing.fieldDataType().getSettings()), indexSettings); } public IndexFieldMapper(MappedFieldType fieldType, EnabledAttributeMapper enabledState, @@ -204,9 +206,10 @@ public class IndexFieldMapper extends AbstractFieldMapper implements RootMapper @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { boolean includeDefaults = params.paramAsBoolean("include_defaults", false); + boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; // if all defaults, no need to write it at all - if (!includeDefaults && fieldType().stored() == Defaults.FIELD_TYPE.stored() && enabledState == Defaults.ENABLED_STATE && customFieldDataSettings == null) { + if (!includeDefaults && fieldType().stored() == Defaults.FIELD_TYPE.stored() && enabledState == Defaults.ENABLED_STATE && hasCustomFieldDataSettings == false) { return builder; } builder.startObject(CONTENT_TYPE); @@ -218,7 +221,7 @@ public class IndexFieldMapper extends AbstractFieldMapper implements RootMapper } if (indexCreatedBefore2x) { - if (customFieldDataSettings != null) { + if (hasCustomFieldDataSettings) { builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); } else if (includeDefaults) { builder.field("fielddata", (Map) fieldType().fieldDataType().getSettings().getAsMap()); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java index 0d65f3569d4..fa4f0e010e1 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java @@ -81,6 +81,7 @@ public class ParentFieldMapper extends AbstractFieldMapper implements RootMapper FIELD_TYPE.setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); FIELD_TYPE.setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); FIELD_TYPE.setNames(new MappedFieldType.Names(NAME)); + FIELD_TYPE.setFieldDataType(new FieldDataType("_parent", settingsBuilder().put(MappedFieldType.Loading.KEY, MappedFieldType.Loading.LAZY_VALUE))); FIELD_TYPE.freeze(); } } @@ -234,11 +235,11 @@ public class ParentFieldMapper extends AbstractFieldMapper implements RootMapper this.type = type; } - public ParentFieldMapper(Settings indexSettings) { - this(Defaults.FIELD_TYPE.clone(), null, null, indexSettings); - this.fieldType = this.fieldType().clone(); - this.fieldType().setFieldDataType(new FieldDataType("_parent", settingsBuilder().put(MappedFieldType.Loading.KEY, MappedFieldType.Loading.LAZY_VALUE))); - this.fieldType().freeze(); + public ParentFieldMapper(Settings indexSettings, MappedFieldType existing) { + this(existing == null ? Defaults.FIELD_TYPE.clone() : existing.clone(), + null, + existing == null ? null : (existing.fieldDataType() == null ? null : existing.fieldDataType().getSettings()), + indexSettings); } public String type() { @@ -325,10 +326,11 @@ public class ParentFieldMapper extends AbstractFieldMapper implements RootMapper return builder; } boolean includeDefaults = params.paramAsBoolean("include_defaults", false); + boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; builder.startObject(CONTENT_TYPE); builder.field("type", type); - if (customFieldDataSettings != null) { + if (hasCustomFieldDataSettings) { builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); } else if (includeDefaults) { builder.field("fielddata", (Map) fieldType().fieldDataType().getSettings().getAsMap()); @@ -339,21 +341,10 @@ public class ParentFieldMapper extends AbstractFieldMapper implements RootMapper @Override public void merge(Mapper mergeWith, MergeResult mergeResult) throws MergeMappingException { - ParentFieldMapper other = (ParentFieldMapper) mergeWith; - if (Objects.equal(type, other.type) == false) { - mergeResult.addConflict("The _parent field's type option can't be changed: [" + type + "]->[" + other.type + "]"); - } - - if (!mergeResult.simulate()) { - ParentFieldMapper fieldMergeWith = (ParentFieldMapper) mergeWith; - this.fieldType = fieldMergeWith.fieldType().clone(); - this.fieldType().freeze(); - - if (fieldMergeWith.customFieldDataSettings != null) { - if (!Objects.equal(fieldMergeWith.customFieldDataSettings, this.customFieldDataSettings)) { - this.customFieldDataSettings = fieldMergeWith.customFieldDataSettings; - } - } + super.merge(mergeWith, mergeResult); + ParentFieldMapper fieldMergeWith = (ParentFieldMapper) mergeWith; + if (Objects.equal(type, fieldMergeWith.type) == false) { + mergeResult.addConflict("The _parent field's type option can't be changed: [" + type + "]->[" + fieldMergeWith.type + "]"); } } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/RoutingFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/RoutingFieldMapper.java index c1bd452df9b..3cdd44b0c8e 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/RoutingFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/RoutingFieldMapper.java @@ -81,8 +81,8 @@ public class RoutingFieldMapper extends AbstractFieldMapper implements RootMappe private String path = Defaults.PATH; - public Builder() { - super(Defaults.NAME, Defaults.FIELD_TYPE); + public Builder(MappedFieldType existing) { + super(Defaults.NAME, existing == null ? Defaults.FIELD_TYPE : existing); } public Builder required(boolean required) { @@ -97,14 +97,14 @@ public class RoutingFieldMapper extends AbstractFieldMapper implements RootMappe @Override public RoutingFieldMapper build(BuilderContext context) { - return new RoutingFieldMapper(fieldType, required, path, fieldDataSettings, context.indexSettings()); + return new RoutingFieldMapper(fieldType, required, path, context.indexSettings()); } } public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - RoutingFieldMapper.Builder builder = routing(); + RoutingFieldMapper.Builder builder = routing(parserContext.mapperService().fullName(NAME)); if (parserContext.indexVersionCreated().before(Version.V_2_0_0)) { parseField(builder, builder.name, node, parserContext); } @@ -151,12 +151,12 @@ public class RoutingFieldMapper extends AbstractFieldMapper implements RootMappe private boolean required; private final String path; - public RoutingFieldMapper(Settings indexSettings) { - this(Defaults.FIELD_TYPE, Defaults.REQUIRED, Defaults.PATH, null, indexSettings); + public RoutingFieldMapper(Settings indexSettings, MappedFieldType existing) { + this(existing == null ? Defaults.FIELD_TYPE.clone() : existing.clone(), Defaults.REQUIRED, Defaults.PATH, indexSettings); } - protected RoutingFieldMapper(MappedFieldType fieldType, boolean required, String path, @Nullable Settings fieldDataSettings, Settings indexSettings) { - super(fieldType, false, fieldDataSettings, indexSettings); + protected RoutingFieldMapper(MappedFieldType fieldType, boolean required, String path, Settings indexSettings) { + super(fieldType, false, null, indexSettings); this.required = required; this.path = path; } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/SizeFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/SizeFieldMapper.java index d8cc7de87f5..26fc8d40f3d 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/SizeFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/SizeFieldMapper.java @@ -61,6 +61,8 @@ public class SizeFieldMapper extends IntegerFieldMapper implements RootMapper { SIZE_FIELD_TYPE.setStored(true); SIZE_FIELD_TYPE.setNumericPrecisionStep(Defaults.PRECISION_STEP_32_BIT); SIZE_FIELD_TYPE.setNames(new MappedFieldType.Names(NAME)); + SIZE_FIELD_TYPE.setIndexAnalyzer(NumericIntegerAnalyzer.buildNamedAnalyzer(Defaults.PRECISION_STEP_32_BIT)); + SIZE_FIELD_TYPE.setSearchAnalyzer(NumericIntegerAnalyzer.buildNamedAnalyzer(Integer.MAX_VALUE)); SIZE_FIELD_TYPE.freeze(); } } @@ -69,8 +71,8 @@ public class SizeFieldMapper extends IntegerFieldMapper implements RootMapper { protected EnabledAttributeMapper enabledState = EnabledAttributeMapper.UNSET_DISABLED; - public Builder() { - super(Defaults.NAME, Defaults.SIZE_FIELD_TYPE, Defaults.PRECISION_STEP_32_BIT); + public Builder(MappedFieldType existing) { + super(Defaults.NAME, existing == null ? Defaults.SIZE_FIELD_TYPE : existing, Defaults.PRECISION_STEP_32_BIT); builder = this; } @@ -82,7 +84,7 @@ public class SizeFieldMapper extends IntegerFieldMapper implements RootMapper { @Override public SizeFieldMapper build(BuilderContext context) { setupFieldType(context); - return new SizeFieldMapper(enabledState, fieldType, fieldDataSettings, context.indexSettings()); + return new SizeFieldMapper(enabledState, fieldType, context.indexSettings()); } @Override @@ -99,7 +101,7 @@ public class SizeFieldMapper extends IntegerFieldMapper implements RootMapper { public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - SizeFieldMapper.Builder builder = size(); + SizeFieldMapper.Builder builder = size(parserContext.mapperService().fullName(NAME)); for (Iterator> iterator = node.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = iterator.next(); String fieldName = Strings.toUnderscoreCase(entry.getKey()); @@ -118,14 +120,12 @@ public class SizeFieldMapper extends IntegerFieldMapper implements RootMapper { private EnabledAttributeMapper enabledState; - public SizeFieldMapper(Settings indexSettings) { - this(Defaults.ENABLED_STATE, Defaults.SIZE_FIELD_TYPE.clone(), null, indexSettings); + public SizeFieldMapper(Settings indexSettings, MappedFieldType existing) { + this(Defaults.ENABLED_STATE, existing == null ? Defaults.SIZE_FIELD_TYPE.clone() : existing.clone(), indexSettings); } - public SizeFieldMapper(EnabledAttributeMapper enabled, MappedFieldType fieldType, @Nullable Settings fieldDataSettings, Settings indexSettings) { - super(fieldType, false, - Defaults.IGNORE_MALFORMED, Defaults.COERCE, fieldDataSettings, - indexSettings, MultiFields.empty(), null); + public SizeFieldMapper(EnabledAttributeMapper enabled, MappedFieldType fieldType, Settings indexSettings) { + super(fieldType, false, Defaults.IGNORE_MALFORMED, Defaults.COERCE, null, indexSettings, MultiFields.empty(), null); this.enabledState = enabled; } 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 056bf81893b..841f13721de 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,12 @@ public class TimestampFieldMapper extends DateFieldMapper implements RootMapper private boolean explicitStore = false; private Boolean ignoreMissing = null; - public Builder() { - super(Defaults.NAME, Defaults.FIELD_TYPE, Defaults.PRECISION_STEP_64_BIT); + public Builder(MappedFieldType existing) { + super(Defaults.NAME, existing == null ? Defaults.FIELD_TYPE : existing, Defaults.PRECISION_STEP_64_BIT); + if (existing != null) { + // if there is an existing type, always use that store value (only matters for < 2.0) + explicitStore = true; + } } DateFieldType fieldType() { @@ -137,7 +141,6 @@ public class TimestampFieldMapper extends DateFieldMapper implements RootMapper @Override public TimestampFieldMapper build(BuilderContext context) { if (explicitStore == false && context.indexCreatedVersion().before(Version.V_2_0_0)) { - assert fieldType.stored(); fieldType.setStored(false); } setupFieldType(context); @@ -160,7 +163,7 @@ public class TimestampFieldMapper extends DateFieldMapper implements RootMapper public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - TimestampFieldMapper.Builder builder = timestamp(); + TimestampFieldMapper.Builder builder = timestamp(parserContext.mapperService().fullName(NAME)); if (parserContext.indexVersionCreated().before(Version.V_2_0_0)) { parseField(builder, builder.name, node, parserContext); } @@ -234,7 +237,10 @@ public class TimestampFieldMapper extends DateFieldMapper implements RootMapper } } - private static MappedFieldType defaultFieldType(Settings settings) { + private static MappedFieldType defaultFieldType(Settings settings, MappedFieldType existing) { + if (existing != null) { + return existing; + } return Version.indexCreated(settings).onOrAfter(Version.V_2_0_0) ? Defaults.FIELD_TYPE : Defaults.PRE_20_FIELD_TYPE; } @@ -245,9 +251,11 @@ public class TimestampFieldMapper extends DateFieldMapper implements RootMapper private final MappedFieldType defaultFieldType; private final Boolean ignoreMissing; - public TimestampFieldMapper(Settings indexSettings) { - this(defaultFieldType(indexSettings).clone(), null, Defaults.ENABLED, Defaults.PATH, Defaults.DEFAULT_TIMESTAMP, - null, Defaults.IGNORE_MALFORMED, Defaults.COERCE, null, indexSettings); + public TimestampFieldMapper(Settings indexSettings, MappedFieldType existing) { + this(defaultFieldType(indexSettings, existing).clone(), null, Defaults.ENABLED, Defaults.PATH, Defaults.DEFAULT_TIMESTAMP, + null, Defaults.IGNORE_MALFORMED, Defaults.COERCE, + existing == null ? null : (existing.fieldDataType() == null ? null : existing.fieldDataType().getSettings()), + indexSettings); } protected TimestampFieldMapper(MappedFieldType fieldType, Boolean docValues, EnabledAttributeMapper enabledState, String path, @@ -258,7 +266,7 @@ public class TimestampFieldMapper extends DateFieldMapper implements RootMapper this.enabledState = enabledState; this.path = path; this.defaultTimestamp = defaultTimestamp; - this.defaultFieldType = defaultFieldType(indexSettings); + this.defaultFieldType = defaultFieldType(indexSettings, null); this.ignoreMissing = ignoreMissing; } @@ -324,9 +332,10 @@ public class TimestampFieldMapper extends DateFieldMapper implements RootMapper boolean includeDefaults = params.paramAsBoolean("include_defaults", false); boolean indexed = fieldType().indexOptions() != IndexOptions.NONE; boolean indexedDefault = Defaults.FIELD_TYPE.indexOptions() != IndexOptions.NONE; + boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; // if all are defaults, no sense to write it at all - if (!includeDefaults && indexed == indexedDefault && customFieldDataSettings == null && + if (!includeDefaults && indexed == indexedDefault && hasCustomFieldDataSettings == false && fieldType().stored() == Defaults.FIELD_TYPE.stored() && enabledState == Defaults.ENABLED && path == Defaults.PATH && fieldType().dateTimeFormatter().format().equals(Defaults.DATE_TIME_FORMATTER.format()) && Defaults.DEFAULT_TIMESTAMP.equals(defaultTimestamp) @@ -359,7 +368,7 @@ public class TimestampFieldMapper extends DateFieldMapper implements RootMapper builder.field("ignore_missing", ignoreMissing); } if (indexCreatedBefore2x) { - if (customFieldDataSettings != null) { + if (hasCustomFieldDataSettings) { builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); } else if (includeDefaults) { builder.field("fielddata", (Map) fieldType().fieldDataType().getSettings().getAsMap()); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java index 56e90f9b841..8ea798b9360 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java @@ -81,15 +81,15 @@ public class TypeFieldMapper extends AbstractFieldMapper implements RootMapper { public static class Builder extends AbstractFieldMapper.Builder { - public Builder() { - super(Defaults.NAME, Defaults.FIELD_TYPE); + public Builder(MappedFieldType existing) { + super(Defaults.NAME, existing == null ? Defaults.FIELD_TYPE : existing); indexName = Defaults.NAME; } @Override public TypeFieldMapper build(BuilderContext context) { fieldType.setNames(new MappedFieldType.Names(name, indexName, indexName, name)); - return new TypeFieldMapper(fieldType, fieldDataSettings, context.indexSettings()); + return new TypeFieldMapper(fieldType, context.indexSettings()); } } @@ -99,7 +99,7 @@ public class TypeFieldMapper extends AbstractFieldMapper implements RootMapper { if (parserContext.indexVersionCreated().onOrAfter(Version.V_2_0_0)) { throw new MapperParsingException(NAME + " is not configurable"); } - TypeFieldMapper.Builder builder = type(); + TypeFieldMapper.Builder builder = type(parserContext.mapperService().fullName(NAME)); parseField(builder, builder.name, node, parserContext); return builder; } @@ -142,12 +142,13 @@ public class TypeFieldMapper extends AbstractFieldMapper implements RootMapper { } } - public TypeFieldMapper(Settings indexSettings) { - this(Defaults.FIELD_TYPE.clone(), null, indexSettings); + public TypeFieldMapper(Settings indexSettings, MappedFieldType existing) { + this(existing == null ? Defaults.FIELD_TYPE.clone() : existing.clone(), + indexSettings); } - public TypeFieldMapper(MappedFieldType fieldType, @Nullable Settings fieldDataSettings, Settings indexSettings) { - super(fieldType, false, fieldDataSettings, indexSettings); + public TypeFieldMapper(MappedFieldType fieldType, Settings indexSettings) { + super(fieldType, false, null, indexSettings); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java index ac6067b64ec..5dfcc203419 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java @@ -82,8 +82,8 @@ public class UidFieldMapper extends AbstractFieldMapper implements RootMapper { public static class Builder extends AbstractFieldMapper.Builder { - public Builder() { - super(Defaults.NAME, Defaults.FIELD_TYPE); + public Builder(MappedFieldType existing) { + super(Defaults.NAME, existing == null ? Defaults.FIELD_TYPE : existing); indexName = Defaults.NAME; } @@ -97,10 +97,10 @@ public class UidFieldMapper extends AbstractFieldMapper implements RootMapper { public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - Builder builder = uid(); if (parserContext.indexVersionCreated().onOrAfter(Version.V_2_0_0)) { throw new MapperParsingException(NAME + " is not configurable"); } + Builder builder = uid(parserContext.mapperService().fullName(NAME)); parseField(builder, builder.name, node, parserContext); return builder; } @@ -130,8 +130,10 @@ public class UidFieldMapper extends AbstractFieldMapper implements RootMapper { } } - public UidFieldMapper(Settings indexSettings) { - this(Defaults.FIELD_TYPE.clone(), null, null, indexSettings); + public UidFieldMapper(Settings indexSettings, MappedFieldType existing) { + this(existing == null ? Defaults.FIELD_TYPE.clone() : existing, null, + existing == null ? null : (existing.fieldDataType() == null ? null : existing.fieldDataType().getSettings()), + indexSettings); } protected UidFieldMapper(MappedFieldType fieldType, Boolean docValues, @Nullable Settings fieldDataSettings, Settings indexSettings) { @@ -218,15 +220,16 @@ public class UidFieldMapper extends AbstractFieldMapper implements RootMapper { return builder; } boolean includeDefaults = params.paramAsBoolean("include_defaults", false); + boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; // if defaults, don't output - if (!includeDefaults && customFieldDataSettings == null) { + if (!includeDefaults && hasCustomFieldDataSettings == false) { return builder; } builder.startObject(CONTENT_TYPE); - if (customFieldDataSettings != null) { + if (hasCustomFieldDataSettings) { builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); } else if (includeDefaults) { builder.field("fielddata", (Map) fieldType().fieldDataType().getSettings().getAsMap()); diff --git a/core/src/main/java/org/elasticsearch/indices/cluster/IndicesClusterStateService.java b/core/src/main/java/org/elasticsearch/indices/cluster/IndicesClusterStateService.java index 6995ecae587..54efdff06f6 100644 --- a/core/src/main/java/org/elasticsearch/indices/cluster/IndicesClusterStateService.java +++ b/core/src/main/java/org/elasticsearch/indices/cluster/IndicesClusterStateService.java @@ -419,7 +419,7 @@ public class IndicesClusterStateService extends AbstractLifecycleComponent(channel)); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/mapping/put/RestPutMappingAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/mapping/put/RestPutMappingAction.java index 0295009c55f..4189d490310 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/mapping/put/RestPutMappingAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/mapping/put/RestPutMappingAction.java @@ -69,6 +69,7 @@ public class RestPutMappingAction extends BaseRestHandler { PutMappingRequest putMappingRequest = putMappingRequest(Strings.splitStringByCommaToArray(request.param("index"))); putMappingRequest.type(request.param("type")); putMappingRequest.source(request.content().toUtf8()); + putMappingRequest.updateAllTypes(request.paramAsBoolean("update_all_types", false)); putMappingRequest.timeout(request.paramAsTime("timeout", putMappingRequest.timeout())); putMappingRequest.masterNodeTimeout(request.paramAsTime("master_timeout", putMappingRequest.masterNodeTimeout())); putMappingRequest.indicesOptions(IndicesOptions.fromRequest(request, putMappingRequest.indicesOptions())); diff --git a/core/src/test/java/org/elasticsearch/action/termvectors/TermVectorsUnitTests.java b/core/src/test/java/org/elasticsearch/action/termvectors/TermVectorsUnitTests.java index dab38d997fa..a981aaff1e0 100644 --- a/core/src/test/java/org/elasticsearch/action/termvectors/TermVectorsUnitTests.java +++ b/core/src/test/java/org/elasticsearch/action/termvectors/TermVectorsUnitTests.java @@ -268,7 +268,7 @@ public class TermVectorsUnitTests extends ElasticsearchTestCase { ft.setStoreTermVectorPositions(true); String ftOpts = AbstractFieldMapper.termVectorOptionsToString(ft); assertThat("with_positions_payloads", equalTo(ftOpts)); - AllFieldMapper.Builder builder = new AllFieldMapper.Builder(); + AllFieldMapper.Builder builder = new AllFieldMapper.Builder(null); boolean exceptiontrown = false; try { TypeParsers.parseTermVector("", ftOpts, builder); diff --git a/core/src/test/java/org/elasticsearch/exists/SimpleExistsTests.java b/core/src/test/java/org/elasticsearch/exists/SimpleExistsTests.java index 78e50de0f50..85280f06d69 100644 --- a/core/src/test/java/org/elasticsearch/exists/SimpleExistsTests.java +++ b/core/src/test/java/org/elasticsearch/exists/SimpleExistsTests.java @@ -104,7 +104,7 @@ public class SimpleExistsTests extends ElasticsearchIntegrationTest { createIndex("test"); client().prepareIndex("test", "type1", "1").setSource("field", 2).execute().actionGet(); client().prepareIndex("test", "type1", "2").setSource("field", 5).execute().actionGet(); - client().prepareIndex("test", "type", "XXX1").setSource("field", "value").execute().actionGet(); + client().prepareIndex("test", "type", "XXX1").setSource("str_field", "value").execute().actionGet(); ensureGreen(); refresh(); ExistsResponse existsResponse = client().prepareExists("test").setQuery(QueryBuilders.rangeQuery("field").gte(6).lte(8)).execute().actionGet(); diff --git a/core/src/test/java/org/elasticsearch/gateway/RecoveryFromGatewayTests.java b/core/src/test/java/org/elasticsearch/gateway/RecoveryFromGatewayTests.java index a35397833a0..23361c83120 100644 --- a/core/src/test/java/org/elasticsearch/gateway/RecoveryFromGatewayTests.java +++ b/core/src/test/java/org/elasticsearch/gateway/RecoveryFromGatewayTests.java @@ -70,21 +70,15 @@ public class RecoveryFromGatewayTests extends ElasticsearchIntegrationTest { .endObject().endObject().string(); assertAcked(prepareCreate("test").addMapping("type1", mapping)); - client().prepareIndex("test", "type1", "10990239").setSource(jsonBuilder().startObject() - .field("_id", "10990239") .startArray("appAccountIds").value(14).value(179).endArray().endObject()).execute().actionGet(); client().prepareIndex("test", "type1", "10990473").setSource(jsonBuilder().startObject() - .field("_id", "10990473") .startArray("appAccountIds").value(14).endArray().endObject()).execute().actionGet(); client().prepareIndex("test", "type1", "10990513").setSource(jsonBuilder().startObject() - .field("_id", "10990513") .startArray("appAccountIds").value(14).value(179).endArray().endObject()).execute().actionGet(); client().prepareIndex("test", "type1", "10990695").setSource(jsonBuilder().startObject() - .field("_id", "10990695") .startArray("appAccountIds").value(14).endArray().endObject()).execute().actionGet(); client().prepareIndex("test", "type1", "11026351").setSource(jsonBuilder().startObject() - .field("_id", "11026351") .startArray("appAccountIds").value(14).endArray().endObject()).execute().actionGet(); refresh(); diff --git a/core/src/test/java/org/elasticsearch/get/GetActionTests.java b/core/src/test/java/org/elasticsearch/get/GetActionTests.java index 5f85a04a057..469dcadcf3a 100644 --- a/core/src/test/java/org/elasticsearch/get/GetActionTests.java +++ b/core/src/test/java/org/elasticsearch/get/GetActionTests.java @@ -25,12 +25,14 @@ import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.admin.indices.alias.Alias; import org.elasticsearch.action.admin.indices.flush.FlushResponse; import org.elasticsearch.action.delete.DeleteResponse; -import org.elasticsearch.action.get.*; +import org.elasticsearch.action.get.GetRequestBuilder; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.get.MultiGetRequest; +import org.elasticsearch.action.get.MultiGetRequestBuilder; +import org.elasticsearch.action.get.MultiGetResponse; import org.elasticsearch.cluster.metadata.IndexMetaData; -import org.elasticsearch.common.Base64; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.lucene.uid.Versions; import org.elasticsearch.common.settings.Settings; @@ -46,7 +48,13 @@ import java.util.Map; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.startsWith; public class GetActionTests extends ElasticsearchIntegrationTest { @@ -248,87 +256,6 @@ public class GetActionTests extends ElasticsearchIntegrationTest { assertThat(getResponse.getSourceAsMap().get("field").toString(), equalTo(fieldValue)); } - @Test - public void getFieldsWithDifferentTypes() throws Exception { - assertAcked(prepareCreate("test").setSettings(Settings.settingsBuilder().put("index.refresh_interval", -1)) - .addMapping("type1", jsonBuilder().startObject().startObject("type1").endObject().endObject()) - .addMapping("type2", jsonBuilder().startObject().startObject("type2") - .startObject("properties") - .startObject("str").field("type", "string").field("store", "yes").endObject() - .startObject("strs").field("type", "string").field("store", "yes").endObject() - .startObject("int").field("type", "integer").field("store", "yes").endObject() - .startObject("ints").field("type", "integer").field("store", "yes").endObject() - .startObject("date").field("type", "date").field("store", "yes").endObject() - .startObject("binary").field("type", "binary").field("store", "yes").endObject() - .endObject() - .endObject().endObject())); - ensureGreen(); - - client().prepareIndex("test", "type1", "1").setSource( - jsonBuilder().startObject() - .field("str", "test") - .field("strs", new String[]{"A", "B", "C"}) - .field("int", 42) - .field("ints", new int[]{1, 2, 3, 4}) - .field("date", "2012-11-13T15:26:14.000Z") - .field("binary", Base64.encodeBytes(new byte[]{1, 2, 3})) - .endObject()).get(); - - client().prepareIndex("test", "type2", "1").setSource( - jsonBuilder().startObject() - .field("str", "test") - .field("strs", new String[]{"A", "B", "C"}) - .field("int", 42) - .field("ints", new int[]{1, 2, 3, 4}) - .field("date", "2012-11-13T15:26:14.000Z") - .field("binary", Base64.encodeBytes(new byte[]{1, 2, 3})) - .endObject()).get(); - - // realtime get with stored source - logger.info("--> realtime get (from source)"); - GetResponse getResponse = client().prepareGet("test", "type1", "1").setFields("str", "strs", "int", "ints", "date", "binary").get(); - assertThat(getResponse.isExists(), equalTo(true)); - assertThat((String) getResponse.getField("str").getValue(), equalTo("test")); - assertThat(getResponse.getField("strs").getValues(), contains((Object) "A", "B", "C")); - assertThat((Long) getResponse.getField("int").getValue(), equalTo(42l)); - assertThat(getResponse.getField("ints").getValues(), contains((Object) 1L, 2L, 3L, 4L)); - assertThat((String) getResponse.getField("date").getValue(), equalTo("2012-11-13T15:26:14.000Z")); - assertThat(getResponse.getField("binary").getValue(), instanceOf(String.class)); // its a String..., not binary mapped - - logger.info("--> realtime get (from stored fields)"); - getResponse = client().prepareGet("test", "type2", "1").setFields("str", "strs", "int", "ints", "date", "binary").get(); - assertThat(getResponse.isExists(), equalTo(true)); - assertThat((String) getResponse.getField("str").getValue(), equalTo("test")); - assertThat(getResponse.getField("strs").getValues(), contains((Object) "A", "B", "C")); - assertThat((Integer) getResponse.getField("int").getValue(), equalTo(42)); - assertThat(getResponse.getField("ints").getValues(), contains((Object) 1, 2, 3, 4)); - assertThat((String) getResponse.getField("date").getValue(), equalTo("2012-11-13T15:26:14.000Z")); - assertThat((BytesReference) getResponse.getField("binary").getValue(), equalTo((BytesReference) new BytesArray(new byte[]{1, 2, 3}))); - - logger.info("--> flush the index, so we load it from it"); - flush(); - - logger.info("--> non realtime get (from source)"); - getResponse = client().prepareGet("test", "type1", "1").setFields("str", "strs", "int", "ints", "date", "binary").get(); - assertThat(getResponse.isExists(), equalTo(true)); - assertThat((String) getResponse.getField("str").getValue(), equalTo("test")); - assertThat(getResponse.getField("strs").getValues(), contains((Object) "A", "B", "C")); - assertThat((Long) getResponse.getField("int").getValue(), equalTo(42l)); - assertThat(getResponse.getField("ints").getValues(), contains((Object) 1L, 2L, 3L, 4L)); - assertThat((String) getResponse.getField("date").getValue(), equalTo("2012-11-13T15:26:14.000Z")); - assertThat(getResponse.getField("binary").getValue(), instanceOf(String.class)); // its a String..., not binary mapped - - logger.info("--> non realtime get (from stored fields)"); - getResponse = client().prepareGet("test", "type2", "1").setFields("str", "strs", "int", "ints", "date", "binary").get(); - assertThat(getResponse.isExists(), equalTo(true)); - assertThat((String) getResponse.getField("str").getValue(), equalTo("test")); - assertThat(getResponse.getField("strs").getValues(), contains((Object) "A", "B", "C")); - assertThat((Integer) getResponse.getField("int").getValue(), equalTo(42)); - assertThat(getResponse.getField("ints").getValues(), contains((Object) 1, 2, 3, 4)); - assertThat((String) getResponse.getField("date").getValue(), equalTo("2012-11-13T15:26:14.000Z")); - assertThat((BytesReference) getResponse.getField("binary").getValue(), equalTo((BytesReference) new BytesArray(new byte[]{1, 2, 3}))); - } - @Test public void testGetDocWithMultivaluedFields() throws Exception { String mapping1 = XContentFactory.jsonBuilder().startObject().startObject("type1") @@ -965,7 +892,11 @@ public class GetActionTests extends ElasticsearchIntegrationTest { " \"refresh_interval\": \"-1\"\n" + " },\n" + " \"mappings\": {\n" + - " \"parentdoc\": {},\n" + + " \"parentdoc\": {\n" + + " \"_ttl\": {\n" + + " \"enabled\": true\n" + + " }\n" + + " },\n" + " \"doc\": {\n" + " \"_parent\": {\n" + " \"type\": \"parentdoc\"\n" + 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 2cabd6d2fdd..4ce54abc16e 100644 --- a/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java +++ b/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java @@ -1832,7 +1832,7 @@ public class InternalEngineTests extends ElasticsearchTestCase { AnalysisService analysisService = new AnalysisService(index, settings); SimilarityLookupService similarityLookupService = new SimilarityLookupService(index, settings); MapperService mapperService = new MapperService(index, settings, analysisService, null, similarityLookupService, null); - DocumentMapper.Builder b = new DocumentMapper.Builder(indexName, settings, rootBuilder); + DocumentMapper.Builder b = new DocumentMapper.Builder(indexName, settings, rootBuilder, mapperService); DocumentMapperParser parser = new DocumentMapperParser(index, settings, mapperService, analysisService, similarityLookupService, null); this.docMapper = b.build(mapperService, parser); diff --git a/core/src/test/java/org/elasticsearch/index/fielddata/ParentChildFieldDataTests.java b/core/src/test/java/org/elasticsearch/index/fielddata/ParentChildFieldDataTests.java index 2d6beac58bc..ad1639a8d28 100644 --- a/core/src/test/java/org/elasticsearch/index/fielddata/ParentChildFieldDataTests.java +++ b/core/src/test/java/org/elasticsearch/index/fielddata/ParentChildFieldDataTests.java @@ -58,10 +58,10 @@ public class ParentChildFieldDataTests extends AbstractFieldDataTests { @Before public void before() throws Exception { mapperService.merge( - childType, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(childType, "_parent", "type=" + parentType).string()), true + childType, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(childType, "_parent", "type=" + parentType).string()), true, false ); mapperService.merge( - grandChildType, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(grandChildType, "_parent", "type=" + childType).string()), true + grandChildType, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(grandChildType, "_parent", "type=" + childType).string()), true, false ); Document d = new Document(); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/FieldMappersLookupTests.java b/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java similarity index 52% rename from core/src/test/java/org/elasticsearch/index/mapper/FieldMappersLookupTests.java rename to core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java index ab336cf7dab..c5885ba019c 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/FieldMappersLookupTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java @@ -21,7 +21,6 @@ package org.elasticsearch.index.mapper; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; -import org.apache.lucene.document.FieldType; import org.elasticsearch.Version; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.settings.Settings; @@ -34,77 +33,112 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; -public class FieldMappersLookupTests extends ElasticsearchTestCase { +public class FieldTypeLookupTests extends ElasticsearchTestCase { public void testEmpty() { - FieldMappersLookup lookup = new FieldMappersLookup(); - assertNull(lookup.fullName("foo")); - assertNull(lookup.indexName("foo")); + FieldTypeLookup lookup = new FieldTypeLookup(); + assertNull(lookup.get("foo")); + assertNull(lookup.getByIndexName("foo")); Collection names = lookup.simpleMatchToFullName("foo"); assertNotNull(names); assertTrue(names.isEmpty()); - names = lookup.simpleMatchToFullName("foo"); + names = lookup.simpleMatchToIndexNames("foo"); assertNotNull(names); assertTrue(names.isEmpty()); - assertNull(lookup.smartName("foo")); - assertNull(lookup.smartNameFieldMapper("foo")); - assertNull(lookup.get("foo")); - Iterator itr = lookup.iterator(); + Iterator itr = lookup.iterator(); assertNotNull(itr); assertFalse(itr.hasNext()); } - public void testNewField() { - FieldMappersLookup lookup = new FieldMappersLookup(); + public void testAddNewField() { + FieldTypeLookup lookup = new FieldTypeLookup(); FakeFieldMapper f = new FakeFieldMapper("foo", "bar"); - FieldMappersLookup lookup2 = lookup.copyAndAddAll(newList(f)); - assertNull(lookup.fullName("foo")); - assertNull(lookup.indexName("bar")); - - FieldMappers mappers = lookup2.fullName("foo"); - assertNotNull(mappers); - assertEquals(1, mappers.mappers().size()); - assertEquals(f, mappers.mapper()); - mappers = lookup2.indexName("bar"); - assertNotNull(mappers); - assertEquals(1, mappers.mappers().size()); - assertEquals(f, mappers.mapper()); + FieldTypeLookup lookup2 = lookup.copyAndAddAll(newList(f)); + assertNull(lookup.get("foo")); + assertNull(lookup.get("bar")); + assertNull(lookup.getByIndexName("foo")); + assertNull(lookup.getByIndexName("bar")); + assertEquals(f.fieldType(), lookup2.get("foo")); + assertNull(lookup.get("bar")); + assertEquals(f.fieldType(), lookup2.getByIndexName("bar")); + assertNull(lookup.getByIndexName("foo")); assertEquals(1, Iterators.size(lookup2.iterator())); } - public void testExtendField() { - FieldMappersLookup lookup = new FieldMappersLookup(); - FakeFieldMapper f = new FakeFieldMapper("foo", "bar"); - FakeFieldMapper other = new FakeFieldMapper("blah", "blah"); - lookup = lookup.copyAndAddAll(newList(f, other)); + 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(newList(f)); + FieldTypeLookup lookup2 = lookup.copyAndAddAll(newList(f2)); + + assertNotSame(originalFieldType, f.fieldType()); + assertSame(f.fieldType(), f2.fieldType()); + assertSame(f.fieldType(), lookup2.get("foo")); + assertSame(f.fieldType(), lookup2.getByIndexName("foo")); + assertEquals(1, Iterators.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(newList(f)); + FieldTypeLookup lookup2 = lookup.copyAndAddAll(newList(f2)); + + 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")); + assertEquals(2, Iterators.size(lookup2.iterator())); + } + + public void testAddExistingFullName() { + FakeFieldMapper f = new FakeFieldMapper("foo", "foo"); FakeFieldMapper f2 = new FakeFieldMapper("foo", "bar"); - FieldMappersLookup lookup2 = lookup.copyAndAddAll(newList(f2)); + MappedFieldType originalFieldType = f.fieldType(); + FieldTypeLookup lookup = new FieldTypeLookup(); + lookup = lookup.copyAndAddAll(newList(f)); + FieldTypeLookup lookup2 = lookup.copyAndAddAll(newList(f2)); - FieldMappers mappers = lookup2.fullName("foo"); - assertNotNull(mappers); - assertEquals(2, mappers.mappers().size()); - - mappers = lookup2.indexName("bar"); - assertNotNull(mappers); - assertEquals(2, mappers.mappers().size()); - assertEquals(3, Iterators.size(lookup2.iterator())); + 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, Iterators.size(lookup2.iterator())); } - public void testIndexName() { - FakeFieldMapper f1 = new FakeFieldMapper("foo", "foo"); - FieldMappersLookup lookup = new FieldMappersLookup(); - lookup = lookup.copyAndAddAll(newList(f1)); + public void testAddExistingBridgeName() { + FakeFieldMapper f = new FakeFieldMapper("foo", "foo"); + FakeFieldMapper f2 = new FakeFieldMapper("bar", "bar"); + FieldTypeLookup lookup = new FieldTypeLookup(); + lookup = lookup.copyAndAddAll(newList(f, f2)); - FieldMappers mappers = lookup.indexName("foo"); - assertNotNull(mappers); - assertEquals(1, mappers.mappers().size()); - assertEquals(f1, mappers.mapper()); + try { + FakeFieldMapper f3 = new FakeFieldMapper("foo", "bar"); + lookup.copyAndAddAll(newList(f3)); + } catch (IllegalStateException e) { + assertTrue(e.getMessage().contains("insane mappings")); + } + + try { + FakeFieldMapper f3 = new FakeFieldMapper("bar", "foo"); + lookup.copyAndAddAll(newList(f3)); + } catch (IllegalStateException e) { + assertTrue(e.getMessage().contains("insane mappings")); + } } + // TODO: add tests for validation + public void testSimpleMatchIndexNames() { FakeFieldMapper f1 = new FakeFieldMapper("foo", "baz"); FakeFieldMapper f2 = new FakeFieldMapper("bar", "boo"); - FieldMappersLookup lookup = new FieldMappersLookup(); + FieldTypeLookup lookup = new FieldTypeLookup(); lookup = lookup.copyAndAddAll(newList(f1, f2)); Collection names = lookup.simpleMatchToIndexNames("b*"); assertTrue(names.contains("baz")); @@ -114,36 +148,22 @@ public class FieldMappersLookupTests extends ElasticsearchTestCase { public void testSimpleMatchFullNames() { FakeFieldMapper f1 = new FakeFieldMapper("foo", "baz"); FakeFieldMapper f2 = new FakeFieldMapper("bar", "boo"); - FieldMappersLookup lookup = new FieldMappersLookup(); + FieldTypeLookup lookup = new FieldTypeLookup(); lookup = lookup.copyAndAddAll(newList(f1, f2)); Collection names = lookup.simpleMatchToFullName("b*"); assertTrue(names.contains("foo")); assertTrue(names.contains("bar")); } - public void testSmartName() { - FakeFieldMapper f1 = new FakeFieldMapper("foo", "realfoo"); - FakeFieldMapper f2 = new FakeFieldMapper("foo", "realbar"); - FakeFieldMapper f3 = new FakeFieldMapper("baz", "realfoo"); - FieldMappersLookup lookup = new FieldMappersLookup(); - lookup = lookup.copyAndAddAll(newList(f1, f2, f3)); - - assertNotNull(lookup.smartName("foo")); - assertEquals(2, lookup.smartName("foo").mappers().size()); - assertNotNull(lookup.smartName("realfoo")); - assertEquals(f1, lookup.smartNameFieldMapper("foo")); - assertEquals(f2, lookup.smartNameFieldMapper("realbar")); - } - public void testIteratorImmutable() { FakeFieldMapper f1 = new FakeFieldMapper("foo", "bar"); - FieldMappersLookup lookup = new FieldMappersLookup(); + FieldTypeLookup lookup = new FieldTypeLookup(); lookup = lookup.copyAndAddAll(newList(f1)); try { - Iterator itr = lookup.iterator(); + Iterator itr = lookup.iterator(); assertTrue(itr.hasNext()); - assertEquals(f1, itr.next()); + assertEquals(f1.fieldType(), itr.next()); itr.remove(); fail("remove should have failed"); } catch (UnsupportedOperationException e) { @@ -151,23 +171,6 @@ public class FieldMappersLookupTests extends ElasticsearchTestCase { } } - public void testGetMapper() { - FakeFieldMapper f1 = new FakeFieldMapper("foo", "bar"); - FieldMappersLookup lookup = new FieldMappersLookup(); - lookup = lookup.copyAndAddAll(newList(f1)); - - assertEquals(f1, lookup.get("foo")); - assertNull(lookup.get("bar")); // get is only by full name - FakeFieldMapper f2 = new FakeFieldMapper("foo", "foo"); - lookup = lookup.copyAndAddAll(newList(f2)); - try { - lookup.get("foo"); - fail("get should have enforced foo is unique"); - } catch (IllegalStateException e) { - // expected - } - } - static List newList(FieldMapper... mapper) { return Lists.newArrayList(mapper); } 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 116bf9cfdfa..971d98d620b 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 @@ -229,11 +229,11 @@ public class CopyToMapperTests extends ElasticsearchSingleNodeTest { DocumentMapper docMapperAfter = parser.parse(mappingAfter); - MergeResult mergeResult = docMapperBefore.merge(docMapperAfter.mapping(), true); + MergeResult mergeResult = docMapperBefore.merge(docMapperAfter.mapping(), true, false); assertThat(Arrays.toString(mergeResult.buildConflicts()), mergeResult.hasConflicts(), equalTo(false)); - docMapperBefore.merge(docMapperAfter.mapping(), false); + docMapperBefore.merge(docMapperAfter.mapping(), false, false); fields = docMapperBefore.mappers().getMapper("copy_test").copyTo().copyToFields(); 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 ae1aeccae91..4c5c7cfd234 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 @@ -64,12 +64,12 @@ public class TokenCountFieldMapperTests extends ElasticsearchSingleNodeTest { .endObject().endObject().string(); DocumentMapper stage2 = parser.parse(stage2Mapping); - MergeResult mergeResult = stage1.merge(stage2.mapping(), true); + MergeResult mergeResult = stage1.merge(stage2.mapping(), true, false); assertThat(mergeResult.hasConflicts(), equalTo(false)); // Just simulated so merge hasn't happened yet assertThat(((TokenCountFieldMapper) stage1.mappers().smartNameFieldMapper("tc")).analyzer(), equalTo("keyword")); - mergeResult = stage1.merge(stage2.mapping(), false); + mergeResult = stage1.merge(stage2.mapping(), false, false); assertThat(mergeResult.hasConflicts(), equalTo(false)); // Just simulated so merge hasn't happened yet assertThat(((TokenCountFieldMapper) stage1.mappers().smartNameFieldMapper("tc")).analyzer(), equalTo("standard")); 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 a9c075b0812..2525b94b9d3 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 @@ -351,7 +351,7 @@ public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest { 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")); - MergeResult mergeResult = defaultMapper.merge(mergeMapper.mapping(), false); + MergeResult mergeResult = defaultMapper.merge(mergeMapper.mapping(), false, false); assertThat("Merging resulting in conflicts: " + Arrays.asList(mergeResult.buildConflicts()), mergeResult.hasConflicts(), is(false)); assertThat(defaultMapper.mappers().getMapper("field"), is(instanceOf(DateFieldMapper.class))); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/geo/GeoPointFieldMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/geo/GeoPointFieldMapperTests.java index 84155a3010f..e9e7a2b4a4c 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/geo/GeoPointFieldMapperTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/geo/GeoPointFieldMapperTests.java @@ -486,7 +486,7 @@ public class GeoPointFieldMapperTests extends ElasticsearchSingleNodeTest { .endObject().endObject().string(); DocumentMapper stage2 = parser.parse(stage2Mapping); - MergeResult mergeResult = stage1.merge(stage2.mapping(), false); + MergeResult mergeResult = stage1.merge(stage2.mapping(), false, false); assertThat(mergeResult.hasConflicts(), equalTo(true)); assertThat(mergeResult.buildConflicts().length, equalTo(2)); // todo better way of checking conflict? @@ -498,7 +498,7 @@ public class GeoPointFieldMapperTests extends ElasticsearchSingleNodeTest { .field("validate", true).field("normalize", true).endObject().endObject() .endObject().endObject().string(); stage2 = parser.parse(stage2Mapping); - mergeResult = stage1.merge(stage2.mapping(), false); + mergeResult = stage1.merge(stage2.mapping(), false, false); assertThat(Arrays.toString(mergeResult.buildConflicts()), mergeResult.hasConflicts(), equalTo(false)); } } 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 7080a6749f3..e9a54feadd2 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 @@ -337,7 +337,7 @@ public class GeoShapeFieldMapperTests extends ElasticsearchSingleNodeTest { .field("orientation", "cw").endObject().endObject().endObject().endObject().string(); DocumentMapper stage2 = parser.parse(stage2Mapping); - MergeResult mergeResult = stage1.merge(stage2.mapping(), false); + MergeResult mergeResult = stage1.merge(stage2.mapping(), false, false); // check correct conflicts assertThat(mergeResult.hasConflicts(), equalTo(true)); assertThat(mergeResult.buildConflicts().length, equalTo(4)); @@ -365,7 +365,7 @@ public class GeoShapeFieldMapperTests extends ElasticsearchSingleNodeTest { .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(); stage2 = parser.parse(stage2Mapping); - mergeResult = stage1.merge(stage2.mapping(), false); + mergeResult = stage1.merge(stage2.mapping(), false, false); // verify mapping changes, and ensure no failures assertThat(Arrays.toString(mergeResult.buildConflicts()), mergeResult.hasConflicts(), equalTo(false)); 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 612a9868789..3a8accd6a64 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 @@ -99,7 +99,7 @@ public class IndexTypeMapperTests extends ElasticsearchSingleNodeTest { .endObject().endObject().string(); DocumentMapper mapperDisabled = parser.parse(mappingWithIndexDisabled); - mapperEnabled.merge(mapperDisabled.mapping(), false); + mapperEnabled.merge(mapperDisabled.mapping(), false, false); assertThat(mapperEnabled.IndexFieldMapper().enabled(), is(false)); } @@ -115,7 +115,7 @@ public class IndexTypeMapperTests extends ElasticsearchSingleNodeTest { .endObject().endObject().string(); DocumentMapper disabledMapper = parser.parse(disabledMapping); - enabledMapper.merge(disabledMapper.mapping(), false); + enabledMapper.merge(disabledMapper.mapping(), false, false); assertThat(enabledMapper.indexMapper().enabled(), is(false)); } 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 db468817f72..30b0fedf789 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 @@ -176,11 +176,11 @@ public class FieldNamesFieldMapperTests extends ElasticsearchSingleNodeTest { DocumentMapper mapperEnabled = parser.parse(enabledMapping); DocumentMapper mapperDisabled = parser.parse(disabledMapping); - mapperEnabled.merge(mapperDisabled.mapping(), false); + mapperEnabled.merge(mapperDisabled.mapping(), false, false); assertFalse(mapperEnabled.rootMapper(FieldNamesFieldMapper.class).fieldType().isEnabled()); mapperEnabled = parser.parse(enabledMapping); - mapperDisabled.merge(mapperEnabled.mapping(), false); + mapperDisabled.merge(mapperEnabled.mapping(), false, false); assertTrue(mapperEnabled.rootMapper(FieldNamesFieldMapper.class).fieldType().isEnabled()); } } 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 a34bf2120f6..72ecc503367 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 @@ -65,13 +65,13 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { .endObject().endObject().endObject().string(); DocumentMapper stage2 = parser.parse(stage2Mapping); - MergeResult mergeResult = stage1.merge(stage2.mapping(), true); + MergeResult mergeResult = stage1.merge(stage2.mapping(), true, false); assertThat(mergeResult.hasConflicts(), equalTo(false)); // since we are simulating, we should not have the age mapping assertThat(stage1.mappers().smartNameFieldMapper("age"), nullValue()); assertThat(stage1.mappers().smartNameFieldMapper("obj1.prop1"), nullValue()); // now merge, don't simulate - mergeResult = stage1.merge(stage2.mapping(), false); + mergeResult = stage1.merge(stage2.mapping(), false, false); // there is still merge failures assertThat(mergeResult.hasConflicts(), equalTo(false)); // but we have the age in @@ -90,7 +90,7 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { DocumentMapper withDynamicMapper = parser.parse(withDynamicMapping); assertThat(withDynamicMapper.root().dynamic(), equalTo(ObjectMapper.Dynamic.FALSE)); - MergeResult mergeResult = mapper.merge(withDynamicMapper.mapping(), false); + MergeResult mergeResult = mapper.merge(withDynamicMapper.mapping(), false, false); assertThat(mergeResult.hasConflicts(), equalTo(false)); assertThat(mapper.root().dynamic(), equalTo(ObjectMapper.Dynamic.FALSE)); } @@ -107,12 +107,12 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { .endObject().endObject().endObject().string(); DocumentMapper nestedMapper = parser.parse(nestedMapping); - MergeResult mergeResult = objectMapper.merge(nestedMapper.mapping(), true); + MergeResult mergeResult = objectMapper.merge(nestedMapper.mapping(), true, false); assertThat(mergeResult.hasConflicts(), equalTo(true)); assertThat(mergeResult.buildConflicts().length, equalTo(1)); assertThat(mergeResult.buildConflicts()[0], equalTo("object mapping [obj] can't be changed from non-nested to nested")); - mergeResult = nestedMapper.merge(objectMapper.mapping(), true); + mergeResult = nestedMapper.merge(objectMapper.mapping(), true, false); assertThat(mergeResult.buildConflicts().length, equalTo(1)); assertThat(mergeResult.buildConflicts()[0], equalTo("object mapping [obj] can't be changed from nested to non-nested")); } @@ -131,7 +131,7 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { DocumentMapper changed = parser.parse(mapping2); assertThat(((NamedAnalyzer) existing.mappers().getMapper("field").fieldType().searchAnalyzer()).name(), equalTo("whitespace")); - MergeResult mergeResult = existing.merge(changed.mapping(), false); + MergeResult mergeResult = existing.merge(changed.mapping(), false, false); assertThat(mergeResult.hasConflicts(), equalTo(false)); assertThat(((NamedAnalyzer) existing.mappers().getMapper("field").fieldType().searchAnalyzer()).name(), equalTo("keyword")); @@ -151,7 +151,7 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { DocumentMapper changed = parser.parse(mapping2); assertThat(((NamedAnalyzer) existing.mappers().getMapper("field").fieldType().searchAnalyzer()).name(), equalTo("whitespace")); - MergeResult mergeResult = existing.merge(changed.mapping(), false); + MergeResult mergeResult = existing.merge(changed.mapping(), false, false); assertThat(mergeResult.hasConflicts(), equalTo(false)); assertThat(((NamedAnalyzer) existing.mappers().getMapper("field").fieldType().searchAnalyzer()).name(), equalTo("standard")); @@ -160,7 +160,7 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { public void testConcurrentMergeTest() throws Throwable { final MapperService mapperService = createIndex("test").mapperService(); - mapperService.merge("test", new CompressedXContent("{\"test\":{}}"), true); + mapperService.merge("test", new CompressedXContent("{\"test\":{}}"), true, false); final DocumentMapper documentMapper = mapperService.documentMapper("test"); DocumentFieldMappers dfm = documentMapper.mappers(); @@ -186,7 +186,7 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { Mapping update = doc.dynamicMappingsUpdate(); assert update != null; lastIntroducedFieldName.set(fieldName); - mapperService.merge("test", new CompressedXContent(update.toString()), false); + mapperService.merge("test", new CompressedXContent(update.toString()), false, false); } } catch (Throwable t) { error.set(t); 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 d63a15b6afb..c7c08b834c9 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 @@ -155,7 +155,7 @@ public class MultiFieldTests extends ElasticsearchSingleNodeTest { stringField("name").store(true) .addMultiField(stringField("indexed").index(true).tokenized(true)) .addMultiField(stringField("not_indexed").index(false).store(true)) - )).build(indexService.mapperService(), mapperParser); + ), indexService.mapperService()).build(indexService.mapperService(), mapperParser); String builtMapping = builderDocMapper.mappingSource().string(); // System.out.println(builtMapping); 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 1235b6f693c..1b8d3cba10c 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 @@ -62,10 +62,10 @@ public class JavaMultiFieldMergeTests extends ElasticsearchSingleNodeTest { mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping2.json"); DocumentMapper docMapper2 = parser.parse(mapping); - MergeResult mergeResult = docMapper.merge(docMapper2.mapping(), true); + MergeResult mergeResult = docMapper.merge(docMapper2.mapping(), true, false); assertThat(Arrays.toString(mergeResult.buildConflicts()), mergeResult.hasConflicts(), equalTo(false)); - docMapper.merge(docMapper2.mapping(), false); + docMapper.merge(docMapper2.mapping(), false, false); assertNotSame(IndexOptions.NONE, docMapper.mappers().getMapper("name").fieldType().indexOptions()); @@ -84,10 +84,10 @@ public class JavaMultiFieldMergeTests extends ElasticsearchSingleNodeTest { mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping3.json"); DocumentMapper docMapper3 = parser.parse(mapping); - mergeResult = docMapper.merge(docMapper3.mapping(), true); + mergeResult = docMapper.merge(docMapper3.mapping(), true, false); assertThat(Arrays.toString(mergeResult.buildConflicts()), mergeResult.hasConflicts(), equalTo(false)); - docMapper.merge(docMapper3.mapping(), false); + docMapper.merge(docMapper3.mapping(), false, false); assertNotSame(IndexOptions.NONE, docMapper.mappers().getMapper("name").fieldType().indexOptions()); @@ -100,10 +100,10 @@ public class JavaMultiFieldMergeTests extends ElasticsearchSingleNodeTest { mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping4.json"); DocumentMapper docMapper4 = parser.parse(mapping); - mergeResult = docMapper.merge(docMapper4.mapping(), true); + mergeResult = docMapper.merge(docMapper4.mapping(), true, false); assertThat(Arrays.toString(mergeResult.buildConflicts()), mergeResult.hasConflicts(), equalTo(false)); - docMapper.merge(docMapper4.mapping(), false); + docMapper.merge(docMapper4.mapping(), false, false); assertNotSame(IndexOptions.NONE, docMapper.mappers().getMapper("name").fieldType().indexOptions()); @@ -135,10 +135,10 @@ public class JavaMultiFieldMergeTests extends ElasticsearchSingleNodeTest { mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/upgrade1.json"); DocumentMapper docMapper2 = parser.parse(mapping); - MergeResult mergeResult = docMapper.merge(docMapper2.mapping(), true); + MergeResult mergeResult = docMapper.merge(docMapper2.mapping(), true, false); assertThat(Arrays.toString(mergeResult.buildConflicts()), mergeResult.hasConflicts(), equalTo(false)); - docMapper.merge(docMapper2.mapping(), false); + docMapper.merge(docMapper2.mapping(), false, false); assertNotSame(IndexOptions.NONE, docMapper.mappers().getMapper("name").fieldType().indexOptions()); @@ -157,10 +157,10 @@ public class JavaMultiFieldMergeTests extends ElasticsearchSingleNodeTest { mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/upgrade2.json"); DocumentMapper docMapper3 = parser.parse(mapping); - mergeResult = docMapper.merge(docMapper3.mapping(), true); + mergeResult = docMapper.merge(docMapper3.mapping(), true, false); assertThat(Arrays.toString(mergeResult.buildConflicts()), mergeResult.hasConflicts(), equalTo(false)); - docMapper.merge(docMapper3.mapping(), false); + docMapper.merge(docMapper3.mapping(), false, false); assertNotSame(IndexOptions.NONE, docMapper.mappers().getMapper("name").fieldType().indexOptions()); @@ -173,12 +173,12 @@ public class JavaMultiFieldMergeTests extends ElasticsearchSingleNodeTest { mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/upgrade3.json"); DocumentMapper docMapper4 = parser.parse(mapping); - mergeResult = docMapper.merge(docMapper4.mapping(), true); + mergeResult = docMapper.merge(docMapper4.mapping(), true, false); assertThat(Arrays.toString(mergeResult.buildConflicts()), mergeResult.hasConflicts(), equalTo(true)); assertThat(mergeResult.buildConflicts()[0], equalTo("mapper [name] has different index values")); assertThat(mergeResult.buildConflicts()[1], equalTo("mapper [name] has different store values")); - mergeResult = docMapper.merge(docMapper4.mapping(), false); + mergeResult = docMapper.merge(docMapper4.mapping(), false, false); assertThat(Arrays.toString(mergeResult.buildConflicts()), mergeResult.hasConflicts(), equalTo(true)); assertNotSame(IndexOptions.NONE, docMapper.mappers().getMapper("name").fieldType().indexOptions()); 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 c429a012f86..50815f55f38 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 @@ -46,8 +46,8 @@ public class SimpleMapperTests extends ElasticsearchSingleNodeTest { DocumentMapperParser mapperParser = indexService.mapperService().documentMapperParser(); DocumentMapper docMapper = doc("test", settings, rootObject("person") - .add(object("name").add(stringField("first").store(true).index(false))) - ).build(indexService.mapperService(), mapperParser); + .add(object("name").add(stringField("first").store(true).index(false))), + indexService.mapperService()).build(indexService.mapperService(), mapperParser); BytesReference json = new BytesArray(copyToBytesFromClasspath("/org/elasticsearch/index/mapper/simple/test1.json")); Document doc = docMapper.parse("person", "1", json).rootDoc(); @@ -124,8 +124,8 @@ public class SimpleMapperTests extends ElasticsearchSingleNodeTest { DocumentMapperParser mapperParser = indexService.mapperService().documentMapperParser(); DocumentMapper docMapper = doc("test", settings, rootObject("person") - .add(object("name").add(stringField("first").store(true).index(false))) - ).build(indexService.mapperService(), mapperParser); + .add(object("name").add(stringField("first").store(true).index(false))), + indexService.mapperService()).build(indexService.mapperService(), mapperParser); BytesReference json = new BytesArray("".getBytes(Charsets.UTF_8)); try { diff --git a/core/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingTests.java index 80ce787e55b..35208ba2a14 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingTests.java @@ -112,7 +112,7 @@ public class SizeMappingTests extends ElasticsearchSingleNodeTest { .endObject().endObject().string(); DocumentMapper disabledMapper = parser.parse(disabledMapping); - enabledMapper.merge(disabledMapper.mapping(), false); + enabledMapper.merge(disabledMapper.mapping(), false, false); assertThat(enabledMapper.SizeFieldMapper().enabled(), is(false)); } } \ No newline at end of file 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 10f33c9025d..389dc21cc22 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 @@ -193,7 +193,7 @@ public class DefaultSourceMappingTests extends ElasticsearchSingleNodeTest { .endObject().endObject().string(); MapperService mapperService = createIndex("test").mapperService(); - mapperService.merge(MapperService.DEFAULT_MAPPING, new CompressedXContent(defaultMapping), true); + mapperService.merge(MapperService.DEFAULT_MAPPING, new CompressedXContent(defaultMapping), true, false); DocumentMapper mapper = mapperService.documentMapperWithAutoCreate("my_type").v1(); assertThat(mapper.type(), equalTo("my_type")); @@ -206,12 +206,12 @@ public class DefaultSourceMappingTests extends ElasticsearchSingleNodeTest { .endObject().endObject().string(); MapperService mapperService = createIndex("test").mapperService(); - mapperService.merge(MapperService.DEFAULT_MAPPING, new CompressedXContent(defaultMapping), true); + mapperService.merge(MapperService.DEFAULT_MAPPING, new CompressedXContent(defaultMapping), true, false); String mapping = XContentFactory.jsonBuilder().startObject().startObject("my_type") .startObject("_source").field("enabled", true).endObject() .endObject().endObject().string(); - mapperService.merge("my_type", new CompressedXContent(mapping), true); + mapperService.merge("my_type", new CompressedXContent(mapping), true, false); DocumentMapper mapper = mapperService.documentMapper("my_type"); assertThat(mapper.type(), equalTo("my_type")); @@ -221,7 +221,7 @@ public class DefaultSourceMappingTests extends ElasticsearchSingleNodeTest { void assertConflicts(String mapping1, String mapping2, DocumentMapperParser parser, String... conflicts) throws IOException { DocumentMapper docMapper = parser.parse(mapping1); docMapper = parser.parse(docMapper.mappingSource().string()); - MergeResult mergeResult = docMapper.merge(parser.parse(mapping2).mapping(), true); + MergeResult mergeResult = docMapper.merge(parser.parse(mapping2).mapping(), true, false); List expectedConflicts = new ArrayList<>(Arrays.asList(conflicts)); for (String conflict : mergeResult.buildConflicts()) { 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 d0e758b81a6..d75637c63ec 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 @@ -498,7 +498,7 @@ public class SimpleStringMappingTests extends ElasticsearchSingleNodeTest { 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(); - MergeResult mergeResult = defaultMapper.merge(parser.parse(updatedMapping).mapping(), false); + MergeResult mergeResult = defaultMapper.merge(parser.parse(updatedMapping).mapping(), false, false); assertFalse(Arrays.toString(mergeResult.buildConflicts()), mergeResult.hasConflicts()); doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder() @@ -513,7 +513,7 @@ public class SimpleStringMappingTests extends ElasticsearchSingleNodeTest { updatedMapping = XContentFactory.jsonBuilder().startObject().startObject("type") .startObject("properties").startObject("field").field("type", "string").startObject("norms").field("enabled", true).endObject() .endObject().endObject().endObject().endObject().string(); - mergeResult = defaultMapper.merge(parser.parse(updatedMapping).mapping(), true); + mergeResult = defaultMapper.merge(parser.parse(updatedMapping).mapping(), true, false); assertTrue(mergeResult.hasConflicts()); assertEquals(1, mergeResult.buildConflicts().length); assertTrue(mergeResult.buildConflicts()[0].contains("cannot enable 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 e8b0ce2db7b..b23b7561f6d 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 @@ -153,7 +153,7 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest { .endObject().endObject().string(); DocumentMapper disabledMapper = parser.parse(disabledMapping); - enabledMapper.merge(disabledMapper.mapping(), false); + enabledMapper.merge(disabledMapper.mapping(), false, false); assertThat(enabledMapper.timestampFieldMapper().enabled(), is(false)); } @@ -514,7 +514,7 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest { .startObject("_timestamp").field("enabled", randomBoolean()).startObject("fielddata").field("loading", "eager").field("format", "array").endObject().field("store", "yes").endObject() .endObject().endObject().string(); - MergeResult mergeResult = docMapper.merge(parser.parse(mapping).mapping(), false); + MergeResult mergeResult = docMapper.merge(parser.parse(mapping).mapping(), false, false); assertThat(mergeResult.buildConflicts().length, equalTo(0)); assertThat(docMapper.timestampFieldMapper().fieldType().fieldDataType().getLoading(), equalTo(MappedFieldType.Loading.EAGER)); assertThat(docMapper.timestampFieldMapper().fieldType().fieldDataType().getFormat(indexSettings), equalTo("array")); @@ -582,7 +582,7 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest { .endObject() .endObject().endObject().string(); - MergeResult mergeResult = docMapper.merge(parser.parse(mapping).mapping(), true); + MergeResult mergeResult = docMapper.merge(parser.parse(mapping).mapping(), true, false); List expectedConflicts = new ArrayList<>(Arrays.asList( "mapper [_timestamp] has different index values", "mapper [_timestamp] has different store values", @@ -621,7 +621,7 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest { .endObject() .endObject().endObject().string(); - MergeResult mergeResult = docMapper.merge(parser.parse(mapping).mapping(), true); + MergeResult mergeResult = docMapper.merge(parser.parse(mapping).mapping(), true, false); List expectedConflicts = new ArrayList<>(); expectedConflicts.add("mapper [_timestamp] has different index values"); expectedConflicts.add("mapper [_timestamp] has different tokenize values"); @@ -681,7 +681,7 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest { void assertConflict(String mapping1, String mapping2, DocumentMapperParser parser, String conflict) throws IOException { DocumentMapper docMapper = parser.parse(mapping1); docMapper = parser.parse(docMapper.mappingSource().string()); - MergeResult mergeResult = docMapper.merge(parser.parse(mapping2).mapping(), true); + MergeResult mergeResult = docMapper.merge(parser.parse(mapping2).mapping(), true, false); assertThat(mergeResult.buildConflicts().length, equalTo(conflict == null ? 0 : 1)); if (conflict != null) { assertThat(mergeResult.buildConflicts()[0], 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 32b75094a8d..1221968ceac 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 @@ -119,7 +119,7 @@ public class TTLMappingTests extends ElasticsearchSingleNodeTest { DocumentMapper mapperWithoutTtl = parser.parse(mappingWithoutTtl); DocumentMapper mapperWithTtl = parser.parse(mappingWithTtl); - MergeResult mergeResult = mapperWithoutTtl.merge(mapperWithTtl.mapping(), false); + MergeResult mergeResult = mapperWithoutTtl.merge(mapperWithTtl.mapping(), false, false); assertThat(mergeResult.hasConflicts(), equalTo(false)); assertThat(mapperWithoutTtl.TTLFieldMapper().enabled(), equalTo(true)); @@ -145,7 +145,7 @@ public class TTLMappingTests extends ElasticsearchSingleNodeTest { DocumentMapper initialMapper = parser.parse(mappingWithTtl); DocumentMapper updatedMapper = parser.parse(updatedMapping); - MergeResult mergeResult = initialMapper.merge(updatedMapper.mapping(), true); + MergeResult mergeResult = initialMapper.merge(updatedMapper.mapping(), true, false); assertThat(mergeResult.hasConflicts(), equalTo(false)); assertThat(initialMapper.TTLFieldMapper().enabled(), equalTo(true)); @@ -159,7 +159,7 @@ public class TTLMappingTests extends ElasticsearchSingleNodeTest { DocumentMapper initialMapper = parser.parse(mappingWithTtl); DocumentMapper updatedMapper = parser.parse(mappingWithTtlDisabled); - MergeResult mergeResult = initialMapper.merge(updatedMapper.mapping(), true); + MergeResult mergeResult = initialMapper.merge(updatedMapper.mapping(), true, false); assertThat(mergeResult.hasConflicts(), equalTo(true)); assertThat(initialMapper.TTLFieldMapper().enabled(), equalTo(true)); @@ -197,7 +197,7 @@ public class TTLMappingTests extends ElasticsearchSingleNodeTest { public void testNoConflictIfNothingSetAndDisabledLater() throws Exception { IndexService indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type"); XContentBuilder mappingWithTtlDisabled = getMappingWithTtlDisabled("7d"); - MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlDisabled.string()), true).mapping(), randomBoolean()); + MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlDisabled.string()), true).mapping(), randomBoolean(), false); assertFalse(mergeResult.hasConflicts()); } @@ -205,7 +205,7 @@ public class TTLMappingTests extends ElasticsearchSingleNodeTest { public void testNoConflictIfNothingSetAndEnabledLater() throws Exception { IndexService indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type"); XContentBuilder mappingWithTtlEnabled = getMappingWithTtlEnabled("7d"); - MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), randomBoolean()); + MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), randomBoolean(), false); assertFalse(mergeResult.hasConflicts()); } @@ -214,7 +214,7 @@ public class TTLMappingTests extends ElasticsearchSingleNodeTest { XContentBuilder mappingWithTtlEnabled = getMappingWithTtlEnabled("7d"); IndexService indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type", mappingWithTtlEnabled); XContentBuilder mappingWithOnlyDefaultSet = getMappingWithOnlyTtlDefaultSet("6m"); - MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithOnlyDefaultSet.string()), true).mapping(), false); + MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithOnlyDefaultSet.string()), true).mapping(), false, false); assertFalse(mergeResult.hasConflicts()); CompressedXContent mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); assertThat(mappingAfterMerge, equalTo(new CompressedXContent("{\"type\":{\"_ttl\":{\"enabled\":true,\"default\":360000},\"properties\":{\"field\":{\"type\":\"string\"}}}}"))); @@ -227,7 +227,7 @@ public class TTLMappingTests extends ElasticsearchSingleNodeTest { CompressedXContent mappingAfterCreation = indexService.mapperService().documentMapper("type").mappingSource(); assertThat(mappingAfterCreation, equalTo(new CompressedXContent("{\"type\":{\"_ttl\":{\"enabled\":false},\"properties\":{\"field\":{\"type\":\"string\"}}}}"))); XContentBuilder mappingWithOnlyDefaultSet = getMappingWithOnlyTtlDefaultSet("6m"); - MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithOnlyDefaultSet.string()), true).mapping(), false); + MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithOnlyDefaultSet.string()), true).mapping(), false, false); assertFalse(mergeResult.hasConflicts()); CompressedXContent mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); assertThat(mappingAfterMerge, equalTo(new CompressedXContent("{\"type\":{\"_ttl\":{\"enabled\":false},\"properties\":{\"field\":{\"type\":\"string\"}}}}"))); @@ -241,7 +241,7 @@ public class TTLMappingTests extends ElasticsearchSingleNodeTest { IndexService indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type", mappingWithTtl); CompressedXContent mappingBeforeMerge = indexService.mapperService().documentMapper("type").mappingSource(); XContentBuilder mappingWithTtlDifferentDefault = getMappingWithTtlEnabled("7d"); - MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlDifferentDefault.string()), true).mapping(), true); + MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlDifferentDefault.string()), true).mapping(), true, false); assertFalse(mergeResult.hasConflicts()); // make sure simulate flag actually worked - no mappings applied CompressedXContent mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); @@ -253,7 +253,7 @@ public class TTLMappingTests extends ElasticsearchSingleNodeTest { indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type", mappingWithoutTtl); mappingBeforeMerge = indexService.mapperService().documentMapper("type").mappingSource(); XContentBuilder mappingWithTtlEnabled = getMappingWithTtlEnabled(); - mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), true); + mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), true, false); assertFalse(mergeResult.hasConflicts()); // make sure simulate flag actually worked - no mappings applied mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); @@ -265,7 +265,7 @@ public class TTLMappingTests extends ElasticsearchSingleNodeTest { indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type", mappingWithoutTtl); mappingBeforeMerge = indexService.mapperService().documentMapper("type").mappingSource(); mappingWithTtlEnabled = getMappingWithTtlEnabled("7d"); - mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), true); + mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), true, false); assertFalse(mergeResult.hasConflicts()); // make sure simulate flag actually worked - no mappings applied mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); @@ -276,7 +276,7 @@ public class TTLMappingTests extends ElasticsearchSingleNodeTest { mappingWithoutTtl = getMappingWithTtlDisabled("6d"); indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type", mappingWithoutTtl); mappingWithTtlEnabled = getMappingWithTtlEnabled("7d"); - mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), false); + mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), false, false); assertFalse(mergeResult.hasConflicts()); // make sure simulate flag actually worked - mappings applied mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); @@ -286,7 +286,7 @@ public class TTLMappingTests extends ElasticsearchSingleNodeTest { // check if switching simulate flag off works if nothing was applied in the beginning indexService = createIndex("testindex", Settings.settingsBuilder().build(), "type"); mappingWithTtlEnabled = getMappingWithTtlEnabled("7d"); - mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), false); + mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingWithTtlEnabled.string()), true).mapping(), false, false); assertFalse(mergeResult.hasConflicts()); // make sure simulate flag actually worked - mappings applied mappingAfterMerge = indexService.mapperService().documentMapper("type").mappingSource(); 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 0c8263d9cde..fb00aadd50b 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 @@ -82,7 +82,7 @@ public class UpdateMappingTests extends ElasticsearchSingleNodeTest { 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 - MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingUpdate.bytes()), true).mapping(), false); + MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingUpdate.bytes()), true).mapping(), false, false); // assure we have no conflicts assertThat(mergeResult.buildConflicts().length, equalTo(0)); // make sure mappings applied @@ -106,7 +106,7 @@ public class UpdateMappingTests extends ElasticsearchSingleNodeTest { IndexService indexService = createIndex("test", Settings.settingsBuilder().build(), "type", mapping); CompressedXContent mappingBeforeUpdate = indexService.mapperService().documentMapper("type").mappingSource(); // simulate like in MetaDataMappingService#putMapping - MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingUpdate.bytes()), true).mapping(), true); + MergeResult mergeResult = indexService.mapperService().documentMapper("type").merge(indexService.mapperService().parse("type", new CompressedXContent(mappingUpdate.bytes()), true).mapping(), true, false); // assure we have conflicts assertThat(mergeResult.buildConflicts().length, equalTo(1)); // make sure simulate flag actually worked - no mappings applied diff --git a/core/src/test/java/org/elasticsearch/index/query/IndexQueryParserFilterDateRangeFormatTests.java b/core/src/test/java/org/elasticsearch/index/query/IndexQueryParserFilterDateRangeFormatTests.java index 5111b36969e..723a485491d 100644 --- a/core/src/test/java/org/elasticsearch/index/query/IndexQueryParserFilterDateRangeFormatTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/IndexQueryParserFilterDateRangeFormatTests.java @@ -57,7 +57,7 @@ public class IndexQueryParserFilterDateRangeFormatTests extends ElasticsearchSin MapperService mapperService = indexService.mapperService(); String mapping = copyToStringFromClasspath("/org/elasticsearch/index/query/mapping.json"); - mapperService.merge("person", new CompressedXContent(mapping), true); + mapperService.merge("person", new CompressedXContent(mapping), true, false); ParsedDocument doc = mapperService.documentMapper("person").parse("person", "1", new BytesArray(copyToBytesFromClasspath("/org/elasticsearch/index/query/data.json"))); assertNotNull(doc.dynamicMappingsUpdate()); client().admin().indices().preparePutMapping("test").setType("person").setSource(doc.dynamicMappingsUpdate().toString()).get(); diff --git a/core/src/test/java/org/elasticsearch/index/query/IndexQueryParserFilterDateRangeTimezoneTests.java b/core/src/test/java/org/elasticsearch/index/query/IndexQueryParserFilterDateRangeTimezoneTests.java index 2d9bacce284..ee878b48024 100644 --- a/core/src/test/java/org/elasticsearch/index/query/IndexQueryParserFilterDateRangeTimezoneTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/IndexQueryParserFilterDateRangeTimezoneTests.java @@ -59,7 +59,7 @@ public class IndexQueryParserFilterDateRangeTimezoneTests extends ElasticsearchS MapperService mapperService = indexService.mapperService(); String mapping = copyToStringFromClasspath("/org/elasticsearch/index/query/mapping.json"); - mapperService.merge("person", new CompressedXContent(mapping), true); + mapperService.merge("person", new CompressedXContent(mapping), true, false); ParsedDocument doc = mapperService.documentMapper("person").parse("person", "1", new BytesArray(copyToBytesFromClasspath("/org/elasticsearch/index/query/data.json"))); assertNotNull(doc.dynamicMappingsUpdate()); client().admin().indices().preparePutMapping("test").setType("person").setSource(doc.dynamicMappingsUpdate().toString()).get(); diff --git a/core/src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java b/core/src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java index 09c58bc7745..284ae0f2d68 100644 --- a/core/src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java @@ -92,7 +92,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest { MapperService mapperService = indexService.mapperService(); String mapping = copyToStringFromClasspath("/org/elasticsearch/index/query/mapping.json"); - mapperService.merge("person", new CompressedXContent(mapping), true); + mapperService.merge("person", new CompressedXContent(mapping), true, false); ParsedDocument doc = mapperService.documentMapper("person").parse("person", "1", new BytesArray(copyToBytesFromClasspath("/org/elasticsearch/index/query/data.json"))); assertNotNull(doc.dynamicMappingsUpdate()); client().admin().indices().preparePutMapping("test").setType("person").setSource(doc.dynamicMappingsUpdate().toString()).get(); diff --git a/core/src/test/java/org/elasticsearch/index/search/child/AbstractChildTests.java b/core/src/test/java/org/elasticsearch/index/search/child/AbstractChildTests.java index e4f8e6c3d16..6488423fb64 100644 --- a/core/src/test/java/org/elasticsearch/index/search/child/AbstractChildTests.java +++ b/core/src/test/java/org/elasticsearch/index/search/child/AbstractChildTests.java @@ -64,8 +64,8 @@ public abstract class AbstractChildTests extends ElasticsearchSingleNodeTest { MapperService mapperService = indexService.mapperService(); // Parent/child parsers require that the parent and child type to be presented in mapping // Sometimes we want a nested object field in the parent type that triggers nonNestedDocsFilter to be used - mapperService.merge(parentType, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(parentType, "nested_field", random().nextBoolean() ? "type=nested" : "type=object").string()), true); - mapperService.merge(childType, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(childType, "_parent", "type=" + parentType, CHILD_SCORE_NAME, "type=double,doc_values=false").string()), true); + mapperService.merge(parentType, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(parentType, "nested_field", random().nextBoolean() ? "type=nested" : "type=object").string()), true, false); + mapperService.merge(childType, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(childType, "_parent", "type=" + parentType, CHILD_SCORE_NAME, "type=double,doc_values=false").string()), true, false); return createSearchContext(indexService); } diff --git a/core/src/test/java/org/elasticsearch/percolator/RecoveryPercolatorTests.java b/core/src/test/java/org/elasticsearch/percolator/RecoveryPercolatorTests.java index 131f72853d6..ec4d65316c3 100644 --- a/core/src/test/java/org/elasticsearch/percolator/RecoveryPercolatorTests.java +++ b/core/src/test/java/org/elasticsearch/percolator/RecoveryPercolatorTests.java @@ -185,16 +185,13 @@ public class RecoveryPercolatorTests extends ElasticsearchIntegrationTest { logger.info("--> Add dummy docs"); client().prepareIndex("test", "type1", "1").setSource("field1", 0).get(); - client().prepareIndex("test", "type2", "1").setSource("field1", "0").get(); + client().prepareIndex("test", "type2", "1").setSource("field1", 1).get(); logger.info("--> register a queries"); for (int i = 1; i <= 100; i++) { client().prepareIndex("test", PercolatorService.TYPE_NAME, Integer.toString(i)) .setSource(jsonBuilder().startObject() .field("query", rangeQuery("field1").from(0).to(i)) - // The type must be set now, because two fields with the same name exist in different types. - // Setting the type to `type1`, makes sure that the range query gets parsed to a Lucene NumericRangeQuery. - .field("type", "type1") .endObject()) .get(); } diff --git a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/nested/NestedAggregatorTest.java b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/nested/NestedAggregatorTest.java index f07d7790ff4..a3da35401e0 100644 --- a/core/src/test/java/org/elasticsearch/search/aggregations/bucket/nested/NestedAggregatorTest.java +++ b/core/src/test/java/org/elasticsearch/search/aggregations/bucket/nested/NestedAggregatorTest.java @@ -117,7 +117,7 @@ public class NestedAggregatorTest extends ElasticsearchSingleNodeTest { IndexSearcher searcher = new IndexSearcher(directoryReader); IndexService indexService = createIndex("test"); - indexService.mapperService().merge("test", new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef("test", "nested_field", "type=nested").string()), true); + indexService.mapperService().merge("test", new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef("test", "nested_field", "type=nested").string()), true, false); SearchContext searchContext = createSearchContext(indexService); AggregationContext context = new AggregationContext(searchContext); diff --git a/core/src/test/java/org/elasticsearch/search/child/ChildQuerySearchTests.java b/core/src/test/java/org/elasticsearch/search/child/ChildQuerySearchTests.java index c3362b9dcd5..a55c7e44cbb 100644 --- a/core/src/test/java/org/elasticsearch/search/child/ChildQuerySearchTests.java +++ b/core/src/test/java/org/elasticsearch/search/child/ChildQuerySearchTests.java @@ -790,7 +790,7 @@ public class ChildQuerySearchTests extends ElasticsearchIntegrationTest { client().prepareIndex("test", "child", "2").setParent("1").setSource("c_field", 1).get(); client().admin().indices().prepareFlush("test").get(); - client().prepareIndex("test", "type1", "3").setSource("p_field", "p_value1").get(); + client().prepareIndex("test", "type1", "3").setSource("p_field", 2).get(); client().admin().indices().prepareFlush("test").get(); SearchResponse searchResponse = client().prepareSearch("test") @@ -1163,7 +1163,7 @@ public class ChildQuerySearchTests extends ElasticsearchIntegrationTest { .addMapping("child1")); ensureGreen(); - client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1", "_parent", "bla").get(); + client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get(); try { client().prepareIndex("test", "child1", "c1").setParent("p1").setSource("c_field", "blue").get(); fail(); diff --git a/core/src/test/java/org/elasticsearch/search/child/ParentFieldLoadingBwcTest.java b/core/src/test/java/org/elasticsearch/search/child/ParentFieldLoadingBwcTest.java index 01f65ccadee..1f3f062f3f5 100644 --- a/core/src/test/java/org/elasticsearch/search/child/ParentFieldLoadingBwcTest.java +++ b/core/src/test/java/org/elasticsearch/search/child/ParentFieldLoadingBwcTest.java @@ -151,7 +151,8 @@ public class ParentFieldLoadingBwcTest extends ElasticsearchIntegrationTest { assertAcked(prepareCreate("test") .setSettings(indexSettings) .addMapping("parent") - .addMapping("child", childMapping(MappedFieldType.Loading.LAZY))); + .addMapping("child", childMapping(MappedFieldType.Loading.LAZY)) + .setUpdateAllTypes(true)); ensureGreen(); client().prepareIndex("test", "parent", "1").setSource("{}").get(); @@ -166,7 +167,8 @@ public class ParentFieldLoadingBwcTest extends ElasticsearchIntegrationTest { assertAcked(prepareCreate("test") .setSettings(indexSettings) .addMapping("parent") - .addMapping("child", "_parent", "type=parent")); + .addMapping("child", "_parent", "type=parent") + .setUpdateAllTypes(true)); ensureGreen(); client().prepareIndex("test", "parent", "1").setSource("{}").get(); @@ -182,7 +184,8 @@ public class ParentFieldLoadingBwcTest extends ElasticsearchIntegrationTest { assertAcked(prepareCreate("test") .setSettings(indexSettings) .addMapping("parent") - .addMapping("child", childMapping(MappedFieldType.Loading.EAGER))); + .addMapping("child", childMapping(MappedFieldType.Loading.EAGER)) + .setUpdateAllTypes(true)); ensureGreen(); client().prepareIndex("test", "parent", "1").setSource("{}").get(); @@ -195,9 +198,10 @@ public class ParentFieldLoadingBwcTest extends ElasticsearchIntegrationTest { logger.info("testing eager global ordinals loading..."); assertAcked(client().admin().indices().prepareDelete("test").get()); assertAcked(prepareCreate("test") - .setSettings(indexSettings) - .addMapping("parent") - .addMapping("child", childMapping(MappedFieldType.Loading.EAGER_GLOBAL_ORDINALS))); + .setSettings(indexSettings) + .addMapping("parent") + .addMapping("child", childMapping(MappedFieldType.Loading.EAGER_GLOBAL_ORDINALS)) + .setUpdateAllTypes(true)); ensureGreen(); // Need to do 2 separate refreshes, otherwise we have 1 segment and then we can't measure if global ordinals @@ -229,6 +233,7 @@ public class ParentFieldLoadingBwcTest extends ElasticsearchIntegrationTest { PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("child") .setSource(childMapping(MappedFieldType.Loading.EAGER_GLOBAL_ORDINALS)) + .setUpdateAllTypes(true) .get(); assertAcked(putMappingResponse); assertBusy(new Runnable() { diff --git a/core/src/test/java/org/elasticsearch/search/child/ParentFieldLoadingTest.java b/core/src/test/java/org/elasticsearch/search/child/ParentFieldLoadingTest.java index a619537c88d..7971f76f111 100644 --- a/core/src/test/java/org/elasticsearch/search/child/ParentFieldLoadingTest.java +++ b/core/src/test/java/org/elasticsearch/search/child/ParentFieldLoadingTest.java @@ -43,8 +43,6 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcke import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; -/** - */ public class ParentFieldLoadingTest extends ElasticsearchIntegrationTest { private final Settings indexSettings = Settings.builder() @@ -55,7 +53,6 @@ public class ParentFieldLoadingTest extends ElasticsearchIntegrationTest { .put(MergePolicyConfig.INDEX_MERGE_ENABLED, false) .build(); - @Test public void testEagerParentFieldLoading() throws Exception { logger.info("testing lazy loading..."); assertAcked(prepareCreate("test") @@ -120,7 +117,6 @@ public class ParentFieldLoadingTest extends ElasticsearchIntegrationTest { assertThat(response.getIndicesStats().getFieldData().getMemorySizeInBytes(), greaterThan(0l)); } - @Test public void testChangingEagerParentFieldLoadingAtRuntime() throws Exception { assertAcked(prepareCreate("test") .setSettings(indexSettings) @@ -137,6 +133,7 @@ public class ParentFieldLoadingTest extends ElasticsearchIntegrationTest { PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("child") .setSource(childMapping(MappedFieldType.Loading.EAGER_GLOBAL_ORDINALS)) + .setUpdateAllTypes(true) .get(); assertAcked(putMappingResponse); assertBusy(new Runnable() { diff --git a/core/src/test/java/org/elasticsearch/search/query/SearchQueryTests.java b/core/src/test/java/org/elasticsearch/search/query/SearchQueryTests.java index d4932e1b8e4..ee08d41c71e 100644 --- a/core/src/test/java/org/elasticsearch/search/query/SearchQueryTests.java +++ b/core/src/test/java/org/elasticsearch/search/query/SearchQueryTests.java @@ -634,7 +634,8 @@ public class SearchQueryTests extends ElasticsearchIntegrationTest { .endObject().endObject()) .addMapping("type2", jsonBuilder().startObject().startObject("type2") .startObject("_type").field("index", index).endObject() - .endObject().endObject())); + .endObject().endObject()) + .setUpdateAllTypes(true)); indexRandom(true, client().prepareIndex("test", "type1", "1").setSource("field1", "value1"), client().prepareIndex("test", "type2", "1").setSource("field1", "value1"), client().prepareIndex("test", "type1", "2").setSource("field1", "value1"), From 00bcce79f7c40ab9ceb6fd98eff413bde3c74696 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Mon, 22 Jun 2015 14:30:40 -0700 Subject: [PATCH 2/6] Simplify root mapper builder creation --- .../index/mapper/MapperBuilders.java | 59 +------------------ .../index/mapper/internal/AllFieldMapper.java | 3 +- .../internal/FieldNamesFieldMapper.java | 7 +-- .../index/mapper/internal/IdFieldMapper.java | 3 +- .../mapper/internal/IndexFieldMapper.java | 2 +- .../mapper/internal/ParentFieldMapper.java | 4 +- .../mapper/internal/RoutingFieldMapper.java | 3 +- .../mapper/internal/SizeFieldMapper.java | 3 +- .../mapper/internal/SourceFieldMapper.java | 4 +- .../index/mapper/internal/TTLFieldMapper.java | 3 +- .../mapper/internal/TimestampFieldMapper.java | 3 +- .../mapper/internal/TypeFieldMapper.java | 3 +- .../index/mapper/internal/UidFieldMapper.java | 3 +- .../mapper/internal/VersionFieldMapper.java | 5 +- .../fielddata/AbstractFieldDataTests.java | 3 +- .../child/ParentFieldLoadingBwcTest.java | 7 +-- 16 files changed, 19 insertions(+), 96 deletions(-) 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 4e919a59433..cc0b27b1713 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/MapperBuilders.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MapperBuilders.java @@ -28,71 +28,14 @@ import org.elasticsearch.index.mapper.ip.IpFieldMapper; import org.elasticsearch.index.mapper.object.ObjectMapper; import org.elasticsearch.index.mapper.object.RootObjectMapper; -/** - * - */ public final class MapperBuilders { - private MapperBuilders() { - - } + private MapperBuilders() {} public static DocumentMapper.Builder doc(String index, Settings settings, RootObjectMapper.Builder objectBuilder, MapperService mapperService) { return new DocumentMapper.Builder(index, settings, objectBuilder, mapperService); } - public static SourceFieldMapper.Builder source() { - return new SourceFieldMapper.Builder(); - } - - public static IdFieldMapper.Builder id(MappedFieldType existing) { - return new IdFieldMapper.Builder(existing); - } - - public static RoutingFieldMapper.Builder routing(MappedFieldType existing) { - return new RoutingFieldMapper.Builder(existing); - } - - public static UidFieldMapper.Builder uid(MappedFieldType existing) { - return new UidFieldMapper.Builder(existing); - } - - public static SizeFieldMapper.Builder size(MappedFieldType existing) { - return new SizeFieldMapper.Builder(existing); - } - - public static VersionFieldMapper.Builder version() { - return new VersionFieldMapper.Builder(); - } - - public static TypeFieldMapper.Builder type(MappedFieldType existing) { - return new TypeFieldMapper.Builder(existing); - } - - public static FieldNamesFieldMapper.Builder fieldNames() { - return new FieldNamesFieldMapper.Builder(); - } - - public static IndexFieldMapper.Builder index(MappedFieldType existing) { - return new IndexFieldMapper.Builder(existing); - } - - public static TimestampFieldMapper.Builder timestamp(MappedFieldType existing) { - return new TimestampFieldMapper.Builder(existing); - } - - public static TTLFieldMapper.Builder ttl() { - return new TTLFieldMapper.Builder(); - } - - public static ParentFieldMapper.Builder parent() { - return new ParentFieldMapper.Builder(); - } - - public static AllFieldMapper.Builder all(MappedFieldType existing) { - return new AllFieldMapper.Builder(existing); - } - public static RootObjectMapper.Builder rootObject(String name) { return new RootObjectMapper.Builder(name); } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java index 10646d596b3..282ea212246 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java @@ -52,7 +52,6 @@ import java.util.Map; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeMapValue; -import static org.elasticsearch.index.mapper.MapperBuilders.all; import static org.elasticsearch.index.mapper.core.TypeParsers.parseField; /** @@ -119,7 +118,7 @@ public class AllFieldMapper extends AbstractFieldMapper implements RootMapper { public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - AllFieldMapper.Builder builder = all(parserContext.mapperService().fullName(NAME)); + Builder builder = new Builder(parserContext.mapperService().fullName(NAME)); // parseField below will happily parse the doc_values setting, but it is then never passed to // the AllFieldMapper ctor in the builder since it is not valid. Here we validate 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 780d36abade..4a6a2b0a4ec 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 @@ -47,7 +47,6 @@ import java.util.Map; import java.util.Objects; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue; -import static org.elasticsearch.index.mapper.MapperBuilders.fieldNames; import static org.elasticsearch.index.mapper.core.TypeParsers.parseField; /** @@ -83,8 +82,8 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper implements RootMa public static class Builder extends AbstractFieldMapper.Builder { private boolean enabled = Defaults.ENABLED; - public Builder() { - super(Defaults.NAME, Defaults.FIELD_TYPE); + public Builder(MappedFieldType existing) { + super(Defaults.NAME, existing == null ? Defaults.FIELD_TYPE : existing); indexName = Defaults.NAME; } @@ -116,7 +115,7 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper implements RootMa throw new IllegalArgumentException("type="+CONTENT_TYPE+" is not supported on indices created before version 1.3.0. Is your cluster running multiple datanode versions?"); } - FieldNamesFieldMapper.Builder builder = fieldNames(); + Builder builder = new Builder(parserContext.mapperService().fullName(NAME)); if (parserContext.indexVersionCreated().before(Version.V_2_0_0)) { parseField(builder, builder.name, node, parserContext); } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java index 65e0d1ef4ed..c66c02e826d 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java @@ -58,7 +58,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import static org.elasticsearch.index.mapper.MapperBuilders.id; import static org.elasticsearch.index.mapper.core.TypeParsers.parseField; /** @@ -120,7 +119,7 @@ public class IdFieldMapper extends AbstractFieldMapper implements RootMapper { if (parserContext.indexVersionCreated().onOrAfter(Version.V_2_0_0)) { throw new MapperParsingException(NAME + " is not configurable"); } - IdFieldMapper.Builder builder = id(parserContext.mapperService().fullName(NAME)); + Builder builder = new Builder(parserContext.mapperService().fullName(NAME)); parseField(builder, builder.name, node, parserContext); for (Iterator> iterator = node.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = iterator.next(); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java index 7035a6f2858..4c650e3dea7 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java @@ -99,7 +99,7 @@ public class IndexFieldMapper extends AbstractFieldMapper implements RootMapper public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - IndexFieldMapper.Builder builder = MapperBuilders.index(parserContext.mapperService().fullName(NAME)); + Builder builder = new Builder(parserContext.mapperService().fullName(NAME)); if (parserContext.indexVersionCreated().before(Version.V_2_0_0)) { parseField(builder, builder.name, node, parserContext); } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java index fa4f0e010e1..bfde40a91c9 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java @@ -64,10 +64,8 @@ import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeMa public class ParentFieldMapper extends AbstractFieldMapper implements RootMapper { public static final String NAME = "_parent"; - public static final String CONTENT_TYPE = "_parent"; - public static class Defaults extends AbstractFieldMapper.Defaults { public static final String NAME = ParentFieldMapper.NAME; @@ -122,7 +120,7 @@ public class ParentFieldMapper extends AbstractFieldMapper implements RootMapper public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - ParentFieldMapper.Builder builder = MapperBuilders.parent(); + Builder builder = new Builder(); for (Iterator> iterator = node.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = iterator.next(); String fieldName = Strings.toUnderscoreCase(entry.getKey()); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/RoutingFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/RoutingFieldMapper.java index 3cdd44b0c8e..29368a54d0f 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/RoutingFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/RoutingFieldMapper.java @@ -44,7 +44,6 @@ import java.util.List; import java.util.Map; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue; -import static org.elasticsearch.index.mapper.MapperBuilders.routing; import static org.elasticsearch.index.mapper.core.TypeParsers.parseField; /** @@ -104,7 +103,7 @@ public class RoutingFieldMapper extends AbstractFieldMapper implements RootMappe public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - RoutingFieldMapper.Builder builder = routing(parserContext.mapperService().fullName(NAME)); + Builder builder = new Builder(parserContext.mapperService().fullName(NAME)); if (parserContext.indexVersionCreated().before(Version.V_2_0_0)) { parseField(builder, builder.name, node, parserContext); } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/SizeFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/SizeFieldMapper.java index 26fc8d40f3d..f5e9c6594b9 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/SizeFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/SizeFieldMapper.java @@ -43,7 +43,6 @@ import java.util.List; import java.util.Map; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue; -import static org.elasticsearch.index.mapper.MapperBuilders.size; import static org.elasticsearch.index.mapper.core.TypeParsers.parseStore; public class SizeFieldMapper extends IntegerFieldMapper implements RootMapper { @@ -101,7 +100,7 @@ public class SizeFieldMapper extends IntegerFieldMapper implements RootMapper { public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - SizeFieldMapper.Builder builder = size(parserContext.mapperService().fullName(NAME)); + Builder builder = new Builder(parserContext.mapperService().fullName(NAME)); for (Iterator> iterator = node.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = iterator.next(); String fieldName = Strings.toUnderscoreCase(entry.getKey()); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java index 7c5d2219883..9a831e32cc8 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java @@ -20,7 +20,6 @@ package org.elasticsearch.index.mapper.internal; import com.google.common.base.Objects; - import org.apache.lucene.document.Field; import org.apache.lucene.document.StoredField; import org.apache.lucene.index.IndexOptions; @@ -63,7 +62,6 @@ import java.util.Map; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeStringValue; -import static org.elasticsearch.index.mapper.MapperBuilders.source; /** * @@ -150,7 +148,7 @@ public class SourceFieldMapper extends AbstractFieldMapper implements RootMapper public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - SourceFieldMapper.Builder builder = source(); + Builder builder = new Builder(); for (Iterator> iterator = node.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = iterator.next(); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/TTLFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/TTLFieldMapper.java index ccc8e7c3466..d30a6228e1b 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/TTLFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/TTLFieldMapper.java @@ -51,7 +51,6 @@ import java.util.Map; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeTimeValue; -import static org.elasticsearch.index.mapper.MapperBuilders.ttl; public class TTLFieldMapper extends LongFieldMapper implements RootMapper { @@ -115,7 +114,7 @@ public class TTLFieldMapper extends LongFieldMapper implements RootMapper { public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - TTLFieldMapper.Builder builder = ttl(); + Builder builder = new Builder(); for (Iterator> iterator = node.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = iterator.next(); String fieldName = Strings.toUnderscoreCase(entry.getKey()); 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 841f13721de..f6624b600cb 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 @@ -50,7 +50,6 @@ import java.util.List; import java.util.Map; import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue; -import static org.elasticsearch.index.mapper.MapperBuilders.timestamp; import static org.elasticsearch.index.mapper.core.TypeParsers.parseDateTimeFormatter; import static org.elasticsearch.index.mapper.core.TypeParsers.parseField; @@ -163,7 +162,7 @@ public class TimestampFieldMapper extends DateFieldMapper implements RootMapper public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - TimestampFieldMapper.Builder builder = timestamp(parserContext.mapperService().fullName(NAME)); + Builder builder = new Builder(parserContext.mapperService().fullName(NAME)); if (parserContext.indexVersionCreated().before(Version.V_2_0_0)) { parseField(builder, builder.name, node, parserContext); } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java index 8ea798b9360..beae9cd0bf5 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java @@ -50,7 +50,6 @@ import java.io.IOException; import java.util.List; import java.util.Map; -import static org.elasticsearch.index.mapper.MapperBuilders.type; import static org.elasticsearch.index.mapper.core.TypeParsers.parseField; /** @@ -99,7 +98,7 @@ public class TypeFieldMapper extends AbstractFieldMapper implements RootMapper { if (parserContext.indexVersionCreated().onOrAfter(Version.V_2_0_0)) { throw new MapperParsingException(NAME + " is not configurable"); } - TypeFieldMapper.Builder builder = type(parserContext.mapperService().fullName(NAME)); + Builder builder = new Builder(parserContext.mapperService().fullName(NAME)); parseField(builder, builder.name, node, parserContext); return builder; } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java index 5dfcc203419..8690e184c19 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java @@ -46,7 +46,6 @@ import java.io.IOException; import java.util.List; import java.util.Map; -import static org.elasticsearch.index.mapper.MapperBuilders.uid; import static org.elasticsearch.index.mapper.core.TypeParsers.parseField; /** @@ -100,7 +99,7 @@ public class UidFieldMapper extends AbstractFieldMapper implements RootMapper { if (parserContext.indexVersionCreated().onOrAfter(Version.V_2_0_0)) { throw new MapperParsingException(NAME + " is not configurable"); } - Builder builder = uid(parserContext.mapperService().fullName(NAME)); + Builder builder = new Builder(parserContext.mapperService().fullName(NAME)); parseField(builder, builder.name, node, parserContext); return builder; } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/VersionFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/VersionFieldMapper.java index 5e33faf0ebb..6dc793c383f 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/VersionFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/VersionFieldMapper.java @@ -42,8 +42,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import static org.elasticsearch.index.mapper.MapperBuilders.version; - /** Mapper for the _version field. */ public class VersionFieldMapper extends AbstractFieldMapper implements RootMapper { @@ -77,11 +75,10 @@ public class VersionFieldMapper extends AbstractFieldMapper implements RootMappe public static class TypeParser implements Mapper.TypeParser { @Override public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { - Builder builder = version(); + Builder builder = new Builder(); for (Iterator> iterator = node.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = iterator.next(); String fieldName = Strings.toUnderscoreCase(entry.getKey()); - Object fieldNode = entry.getValue(); if (fieldName.equals(DOC_VALUES_FORMAT) && parserContext.indexVersionCreated().before(Version.V_2_0_0)) { // ignore in 1.x, reject in 2.x iterator.remove(); diff --git a/core/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataTests.java b/core/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataTests.java index fd3853bcf9d..8cee12de94c 100644 --- a/core/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataTests.java +++ b/core/src/test/java/org/elasticsearch/index/fielddata/AbstractFieldDataTests.java @@ -34,6 +34,7 @@ import org.elasticsearch.index.mapper.Mapper.BuilderContext; import org.elasticsearch.index.mapper.MapperBuilders; import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.IndexService; +import org.elasticsearch.index.mapper.internal.ParentFieldMapper; import org.elasticsearch.indices.fielddata.cache.IndicesFieldDataCache; import org.elasticsearch.test.ElasticsearchSingleNodeTest; import org.junit.After; @@ -85,7 +86,7 @@ public abstract class AbstractFieldDataTests extends ElasticsearchSingleNodeTest } else if (type.getType().equals("geo_point")) { fieldType = MapperBuilders.geoPointField(fieldName).docValues(docValues).fieldDataSettings(type.getSettings()).build(context).fieldType(); } else if (type.getType().equals("_parent")) { - fieldType = MapperBuilders.parent().type(fieldName).build(context).fieldType(); + fieldType = new ParentFieldMapper.Builder().type(fieldName).build(context).fieldType(); } else if (type.getType().equals("binary")) { fieldType = MapperBuilders.binaryField(fieldName).docValues(docValues).fieldDataSettings(type.getSettings()).build(context).fieldType(); } else { diff --git a/core/src/test/java/org/elasticsearch/search/child/ParentFieldLoadingBwcTest.java b/core/src/test/java/org/elasticsearch/search/child/ParentFieldLoadingBwcTest.java index 1f3f062f3f5..944ecacfc3a 100644 --- a/core/src/test/java/org/elasticsearch/search/child/ParentFieldLoadingBwcTest.java +++ b/core/src/test/java/org/elasticsearch/search/child/ParentFieldLoadingBwcTest.java @@ -55,8 +55,6 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFa import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; -/** - */ public class ParentFieldLoadingBwcTest extends ElasticsearchIntegrationTest { private final Settings indexSettings = Settings.builder() @@ -68,7 +66,6 @@ public class ParentFieldLoadingBwcTest extends ElasticsearchIntegrationTest { .put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_6_0) .build(); - @Test @LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elasticsearch/elasticsearch/issues/9270") public void testParentFieldDataCacheBug() throws Exception { assertAcked(prepareCreate("test") @@ -145,7 +142,6 @@ public class ParentFieldLoadingBwcTest extends ElasticsearchIntegrationTest { assertThat(indicesStatsResponse.getTotal().getFieldData().getFields().get("_parent"), equalTo(0l)); } - @Test public void testEagerParentFieldLoading() throws Exception { logger.info("testing lazy loading..."); assertAcked(prepareCreate("test") @@ -214,8 +210,7 @@ public class ParentFieldLoadingBwcTest extends ElasticsearchIntegrationTest { response = client().admin().cluster().prepareClusterStats().get(); assertThat(response.getIndicesStats().getFieldData().getMemorySizeInBytes(), greaterThan(fielddataSizeDefault)); } - - @Test + public void testChangingEagerParentFieldLoadingAtRuntime() throws Exception { assertAcked(prepareCreate("test") .setSettings(indexSettings) From 18ec76aae882194fc7cbb3d927f69da5767e0f42 Mon Sep 17 00:00:00 2001 From: Adrien Grand Date: Tue, 23 Jun 2015 11:44:07 +0200 Subject: [PATCH 3/6] Better test reuse of existing mappings for dynamic mappings. --- .../index/mapper/DocumentParser.java | 39 ++++++++------- .../index/mapper/core/ByteFieldMapper.java | 4 +- .../index/mapper/core/DateFieldMapper.java | 5 +- .../index/mapper/core/DoubleFieldMapper.java | 6 ++- .../index/mapper/core/FloatFieldMapper.java | 6 ++- .../index/mapper/core/IntegerFieldMapper.java | 4 +- .../index/mapper/core/LongFieldMapper.java | 5 +- .../index/mapper/core/NumberFieldMapper.java | 3 +- .../index/mapper/core/ShortFieldMapper.java | 5 +- .../index/mapper/ip/IpFieldMapper.java | 6 ++- .../index/mapper/DynamicMappingTests.java | 48 +++++++++++++++++++ 11 files changed, 106 insertions(+), 25 deletions(-) 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 f8e422f1c81..c400f12e41e 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java @@ -464,6 +464,7 @@ class DocumentParser implements Closeable { if (builder == null) { builder = MapperBuilders.longField(currentFieldName); } + break; case DOUBLE: builder = context.root().findTemplateBuilder(context, currentFieldName, "double"); if (builder == null) { @@ -475,6 +476,7 @@ class DocumentParser implements Closeable { if (builder == null) { builder = MapperBuilders.integerField(currentFieldName); } + break; case FLOAT: builder = context.root().findTemplateBuilder(context, currentFieldName, "float"); if (builder == null) { @@ -628,26 +630,31 @@ class DocumentParser implements Closeable { if (existingFieldType != null) { // create a builder of the same type builder = createBuilderFromFieldType(context, existingFieldType, currentFieldName); + if (builder != null) { + // best-effort to not introduce a conflict + if (builder instanceof StringFieldMapper.Builder) { + StringFieldMapper.Builder stringBuilder = (StringFieldMapper.Builder) builder; + stringBuilder.store(existingFieldType.stored()); + stringBuilder.indexOptions(existingFieldType.indexOptions()); + stringBuilder.tokenized(existingFieldType.tokenized()); + stringBuilder.omitNorms(existingFieldType.omitNorms()); + stringBuilder.docValues(existingFieldType.hasDocValues()); + stringBuilder.indexAnalyzer(existingFieldType.indexAnalyzer()); + stringBuilder.searchAnalyzer(existingFieldType.searchAnalyzer()); + } else if (builder instanceof NumberFieldMapper.Builder) { + NumberFieldMapper.Builder numberBuilder = (NumberFieldMapper.Builder) builder; + numberBuilder.store(existingFieldType.stored()); + numberBuilder.indexOptions(existingFieldType.indexOptions()); + numberBuilder.tokenized(existingFieldType.tokenized()); + numberBuilder.omitNorms(existingFieldType.omitNorms()); + numberBuilder.docValues(existingFieldType.hasDocValues()); + numberBuilder.precisionStep(existingFieldType.numericPrecisionStep()); + } + } } if (builder == null) { builder = createBuilderFromDynamicValue(context, token, currentFieldName); } - if (existingFieldType != null) { - // best-effort to not introduce a conflict - if (builder instanceof StringFieldMapper.Builder) { - StringFieldMapper.Builder stringBuilder = (StringFieldMapper.Builder) builder; - stringBuilder.store(existingFieldType.stored()); - stringBuilder.indexOptions(existingFieldType.indexOptions()); - stringBuilder.omitNorms(existingFieldType.omitNorms()); - stringBuilder.docValues(existingFieldType.hasDocValues()); - } else if (builder instanceof NumberFieldMapper.Builder) { - NumberFieldMapper.Builder numberBuilder = (NumberFieldMapper.Builder) builder; - numberBuilder.store(existingFieldType.stored()); - numberBuilder.indexOptions(existingFieldType.indexOptions()); - numberBuilder.omitNorms(existingFieldType.omitNorms()); - numberBuilder.docValues(existingFieldType.hasDocValues()); - } - } Mapper mapper = builder.build(builderContext); mapper = parseAndMergeUpdate(mapper, context); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java index 96eecc72b8f..24e4c99e8cd 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java @@ -121,7 +121,9 @@ public class ByteFieldMapper extends NumberFieldMapper { } static final class ByteFieldType extends NumberFieldType { - public ByteFieldType() {} + public ByteFieldType() { + super(NumericType.INT); + } protected ByteFieldType(ByteFieldType ref) { super(ref); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java index 74ecffa6df9..54950cfe8f9 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java @@ -20,6 +20,7 @@ package org.elasticsearch.index.mapper.core; import org.apache.lucene.document.Field; +import org.apache.lucene.document.FieldType.NumericType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Terms; @@ -221,7 +222,9 @@ public class DateFieldMapper extends NumberFieldMapper { protected TimeUnit timeUnit = Defaults.TIME_UNIT; protected DateMathParser dateMathParser = new DateMathParser(dateTimeFormatter); - public DateFieldType() {} + public DateFieldType() { + super(NumericType.LONG); + } protected DateFieldType(DateFieldType ref) { super(ref); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java index 794a0284b21..b11c2f4384d 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java @@ -20,9 +20,11 @@ package org.elasticsearch.index.mapper.core; import com.carrotsearch.hppc.DoubleArrayList; + import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.document.Field; +import org.apache.lucene.document.FieldType.NumericType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.Terms; import org.apache.lucene.search.NumericRangeQuery; @@ -126,7 +128,9 @@ public class DoubleFieldMapper extends NumberFieldMapper { static final class DoubleFieldType extends NumberFieldType { - public DoubleFieldType() {} + public DoubleFieldType() { + super(NumericType.DOUBLE); + } protected DoubleFieldType(DoubleFieldType ref) { super(ref); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java index 610b27302cf..a83902fb18b 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java @@ -20,9 +20,11 @@ package org.elasticsearch.index.mapper.core; import com.carrotsearch.hppc.FloatArrayList; + import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.document.Field; +import org.apache.lucene.document.FieldType.NumericType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.Terms; import org.apache.lucene.search.NumericRangeQuery; @@ -127,7 +129,9 @@ public class FloatFieldMapper extends NumberFieldMapper { static final class FloatFieldType extends NumberFieldType { - public FloatFieldType() {} + public FloatFieldType() { + super(NumericType.FLOAT); + } protected FloatFieldType(FloatFieldType ref) { super(ref); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java index 17fdcbeae6d..147fea564cc 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java @@ -130,7 +130,9 @@ public class IntegerFieldMapper extends NumberFieldMapper { public static final class IntegerFieldType extends NumberFieldType { - public IntegerFieldType() {} + public IntegerFieldType() { + super(NumericType.INT); + } protected IntegerFieldType(IntegerFieldType ref) { super(ref); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java index 5e7e41372d6..388450aa01b 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java @@ -22,6 +22,7 @@ package org.elasticsearch.index.mapper.core; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.document.Field; +import org.apache.lucene.document.FieldType.NumericType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.Terms; import org.apache.lucene.search.NumericRangeQuery; @@ -128,7 +129,9 @@ public class LongFieldMapper extends NumberFieldMapper { public static class LongFieldType extends NumberFieldType { - public LongFieldType() {} + public LongFieldType() { + super(NumericType.LONG); + } protected LongFieldType(LongFieldType ref) { super(ref); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java index a9ebe135330..71bf4694a39 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java @@ -135,12 +135,13 @@ public abstract class NumberFieldMapper extends AbstractFieldMapper implements A public static abstract class NumberFieldType extends MappedFieldType { - public NumberFieldType() { + public NumberFieldType(NumericType numericType) { super(AbstractFieldMapper.Defaults.FIELD_TYPE); setTokenized(false); setOmitNorms(true); setIndexOptions(IndexOptions.DOCS); setStoreTermVectors(false); + setNumericType(numericType); } protected NumberFieldType(NumberFieldType ref) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java index 2c7496d20fc..61cb08fc56e 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java @@ -22,6 +22,7 @@ package org.elasticsearch.index.mapper.core; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.document.Field; +import org.apache.lucene.document.FieldType.NumericType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.Terms; import org.apache.lucene.search.NumericRangeQuery; @@ -126,7 +127,9 @@ public class ShortFieldMapper extends NumberFieldMapper { static final class ShortFieldType extends NumberFieldType { - public ShortFieldType() {} + public ShortFieldType() { + super(NumericType.INT); + } protected ShortFieldType(ShortFieldType ref) { super(ref); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java index 5b659497048..54218fa1ecb 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java @@ -20,8 +20,10 @@ package org.elasticsearch.index.mapper.ip; import com.google.common.net.InetAddresses; + import org.apache.lucene.analysis.NumericTokenStream; import org.apache.lucene.document.Field; +import org.apache.lucene.document.FieldType.NumericType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.search.NumericRangeQuery; import org.apache.lucene.search.Query; @@ -158,7 +160,9 @@ public class IpFieldMapper extends NumberFieldMapper { public static final class IpFieldType extends NumberFieldType { - public IpFieldType() {} + public IpFieldType() { + super(NumericType.LONG); + } protected IpFieldType(IpFieldType ref) { super(ref); diff --git a/core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingTests.java index 920c7221a0e..f3877e4820c 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/DynamicMappingTests.java @@ -30,6 +30,8 @@ import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.IndexService; +import org.elasticsearch.index.mapper.core.IntegerFieldMapper; +import org.elasticsearch.index.mapper.core.StringFieldMapper; import org.elasticsearch.test.ElasticsearchSingleNodeTest; import java.io.IOException; @@ -360,4 +362,50 @@ public class DynamicMappingTests extends ElasticsearchSingleNodeTest { .endObject().endObject() .endObject().endObject().endObject().string(), serialize(update)); } + + public void testReuseExistingMappings() throws IOException, Exception { + IndexService indexService = createIndex("test", Settings.EMPTY, "type", "my_field1", "type=string,store=yes", "my_field2", "type=integer,precision_step=10"); + + // Even if the dynamic type of our new field is long, we already have a mapping for the same field + // of type string so it should be mapped as a string + DocumentMapper newMapper = indexService.mapperService().documentMapperWithAutoCreate("type2").v1(); + Mapper update = parse(newMapper, indexService.mapperService().documentMapperParser(), + XContentFactory.jsonBuilder().startObject().field("my_field1", 42).endObject()); + Mapper myField1Mapper = null; + for (Mapper m : update) { + if (m.name().equals("my_field1")) { + myField1Mapper = m; + } + } + assertNotNull(myField1Mapper); + // same type + assertTrue(myField1Mapper instanceof StringFieldMapper); + // and same option + assertTrue(((StringFieldMapper) myField1Mapper).fieldType().stored()); + + // Even if dynamic mappings would map a numeric field as a long, here it should map it as a integer + // since we already have a mapping of type integer + update = parse(newMapper, indexService.mapperService().documentMapperParser(), + XContentFactory.jsonBuilder().startObject().field("my_field2", 42).endObject()); + Mapper myField2Mapper = null; + for (Mapper m : update) { + if (m.name().equals("my_field2")) { + myField2Mapper = m; + } + } + assertNotNull(myField2Mapper); + // same type + assertTrue(myField2Mapper instanceof IntegerFieldMapper); + // and same option + assertEquals(10, ((IntegerFieldMapper) myField2Mapper).fieldType().numericPrecisionStep()); + + // This can't work + try { + parse(newMapper, indexService.mapperService().documentMapperParser(), + XContentFactory.jsonBuilder().startObject().field("my_field2", "foobar").endObject()); + fail("Cannot succeed, incompatible types"); + } catch (MapperParsingException e) { + // expected + } + } } From 33339ab288be675f92635b52d1a992c72a8a55ab Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Tue, 23 Jun 2015 08:59:30 -0700 Subject: [PATCH 4/6] Addressed PR comments --- .../create/CreateIndexClusterStateUpdateRequest.java | 1 + .../elasticsearch/index/mapper/DocumentParser.java | 4 ++-- .../elasticsearch/index/mapper/FieldTypeLookup.java | 8 +++----- .../index/mapper/MappedFieldTypeReference.java | 12 ++++++------ .../index/mapper/core/AbstractFieldMapper.java | 11 +++++++---- .../index/mapper/core/NumberFieldMapper.java | 2 +- .../index/mapper/internal/AllFieldMapper.java | 3 +-- .../index/mapper/internal/IdFieldMapper.java | 5 ++--- .../index/mapper/internal/IndexFieldMapper.java | 5 ++--- .../index/mapper/internal/ParentFieldMapper.java | 3 +-- .../index/mapper/internal/TimestampFieldMapper.java | 5 ++--- .../index/mapper/internal/UidFieldMapper.java | 5 ++--- 12 files changed, 30 insertions(+), 34 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java b/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java index d915ad98165..16a399faff1 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java @@ -129,6 +129,7 @@ public class CreateIndexClusterStateUpdateRequest extends ClusterStateUpdateRequ return blocks; } + /** True if all fields that span multiple types should be updated, false otherwise */ public boolean updateAllTypes() { return updateAllTypes; } 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 c400f12e41e..441a798fa0f 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java @@ -529,7 +529,7 @@ class DocumentParser implements Closeable { builder = MapperBuilders.longField(currentFieldName); } return builder; - } catch (Exception e) { + } catch (NumberFormatException e) { // not a long number } try { @@ -539,7 +539,7 @@ class DocumentParser implements Closeable { builder = MapperBuilders.doubleField(currentFieldName); } return builder; - } catch (Exception e) { + } catch (NumberFormatException e) { // not a long number } } 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 23c77fd5248..c4eab151a56 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java @@ -24,10 +24,8 @@ import com.google.common.collect.Iterators; import com.google.common.collect.Sets; import org.elasticsearch.common.collect.CopyOnWriteHashMap; import org.elasticsearch.common.regex.Regex; -import org.elasticsearch.index.mapper.object.ObjectMapper; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -101,7 +99,7 @@ class FieldTypeLookup implements Iterable { } /** - * Checks if the give mapper's field types are compatibile with existing field types. + * Checks if the given mappers' field types are compatible with existing field types. * If any are not compatible, an IllegalArgumentException is thrown. * If updateAllTypes is true, only basic compatibility is checked. */ @@ -109,7 +107,7 @@ class FieldTypeLookup implements Iterable { for (FieldMapper fieldMapper : newFieldMappers) { MappedFieldTypeReference ref = fullNameToFieldType.get(fieldMapper.fieldType().names().fullName()); if (ref != null) { - boolean strict = ref.getRefCount() > 1 && updateAllTypes == false; + boolean strict = ref.getNumAssociatedMappers() > 1 && updateAllTypes == false; List conflicts = new ArrayList<>(); ref.get().checkCompatibility(fieldMapper.fieldType(), conflicts, strict); if (conflicts.isEmpty() == false) { @@ -120,7 +118,7 @@ class FieldTypeLookup implements Iterable { // field type for the index name must be compatible too MappedFieldTypeReference indexNameRef = fullNameToFieldType.get(fieldMapper.fieldType().names().indexName()); if (indexNameRef != null) { - boolean strict = indexNameRef.getRefCount() > 1 && updateAllTypes == false; + boolean strict = indexNameRef.getNumAssociatedMappers() > 1 && updateAllTypes == false; List conflicts = new ArrayList<>(); indexNameRef.get().checkCompatibility(fieldMapper.fieldType(), conflicts, strict); if (conflicts.isEmpty() == false) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldTypeReference.java b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldTypeReference.java index 8153f004cee..d3c6b83a6a3 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldTypeReference.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldTypeReference.java @@ -23,12 +23,12 @@ package org.elasticsearch.index.mapper; */ public class MappedFieldTypeReference { private MappedFieldType fieldType; // the current field type this reference points to - private int refCount; + private int numAssociatedMappers; public MappedFieldTypeReference(MappedFieldType fieldType) { fieldType.freeze(); // ensure frozen this.fieldType = fieldType; - this.refCount = 1; + this.numAssociatedMappers = 1; } public MappedFieldType get() { @@ -40,11 +40,11 @@ public class MappedFieldTypeReference { this.fieldType = fieldType; } - public int getRefCount() { - return refCount; + public int getNumAssociatedMappers() { + return numAssociatedMappers; } - public void incRefCount() { - ++refCount; + public void incrementAssociatedMappers() { + ++numAssociatedMappers; } } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java index fe24c10b4af..e60cba25c87 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java @@ -350,7 +350,7 @@ public abstract class AbstractFieldMapper implements FieldMapper { if (ref.get().equals(fieldType()) == false) { throw new IllegalStateException("Cannot overwrite field type reference to unequal reference"); } - ref.incRefCount(); + ref.incrementAssociatedMappers(); this.fieldTypeRef = ref; } @@ -409,7 +409,7 @@ public abstract class AbstractFieldMapper implements FieldMapper { } AbstractFieldMapper fieldMergeWith = (AbstractFieldMapper) mergeWith; List subConflicts = new ArrayList<>(); // TODO: just expose list from MergeResult? - boolean strict = this.fieldTypeRef.getRefCount() > 1 && mergeResult.updateAllTypes() == false; + boolean strict = this.fieldTypeRef.getNumAssociatedMappers() > 1 && mergeResult.updateAllTypes() == false; fieldType().checkCompatibility(fieldMergeWith.fieldType(), subConflicts, strict); for (String conflict : subConflicts) { mergeResult.addConflict(conflict); @@ -482,8 +482,7 @@ public abstract class AbstractFieldMapper implements FieldMapper { } TreeMap orderedFielddataSettings = new TreeMap<>(); - boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; - if (hasCustomFieldDataSettings) { + if (hasCustomFieldDataSettings()) { orderedFielddataSettings.putAll(customFieldDataSettings.getAsMap()); builder.field("fielddata", orderedFielddataSettings); } else if (includeDefaults) { @@ -563,6 +562,10 @@ public abstract class AbstractFieldMapper implements FieldMapper { } } + protected boolean hasCustomFieldDataSettings() { + return customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; + } + protected abstract String contentType(); @Override diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java index 71bf4694a39..070d0d0a001 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java @@ -319,7 +319,7 @@ public abstract class NumberFieldMapper extends AbstractFieldMapper implements A return; } NumberFieldMapper nfmMergeWith = (NumberFieldMapper) mergeWith; - if (this.fieldTypeRef.getRefCount() > 1 && mergeResult.updateAllTypes() == false) { + if (this.fieldTypeRef.getNumAssociatedMappers() > 1 && mergeResult.updateAllTypes() == false) { if (fieldType().numericPrecisionStep() != nfmMergeWith.fieldType().numericPrecisionStep()) { mergeResult.addConflict("mapper [" + fieldType().names().fullName() + "] is used by multiple types. Set update_all_types to true to update precision_step across all types."); } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java index 282ea212246..68539208fd3 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java @@ -314,8 +314,7 @@ public class AllFieldMapper extends AbstractFieldMapper implements RootMapper { builder.field("similarity", SimilarityLookupService.DEFAULT_SIMILARITY); } - boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; - if (hasCustomFieldDataSettings) { + if (hasCustomFieldDataSettings()) { builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); } else if (includeDefaults) { builder.field("fielddata", (Map) fieldType().fieldDataType().getSettings().getAsMap()); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java index c66c02e826d..5a6c7e1c121 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java @@ -310,13 +310,12 @@ public class IdFieldMapper extends AbstractFieldMapper implements RootMapper { return builder; } boolean includeDefaults = params.paramAsBoolean("include_defaults", false); - boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; // if all are defaults, no sense to write it at all if (!includeDefaults && fieldType().stored() == Defaults.FIELD_TYPE.stored() && fieldType().indexOptions() == Defaults.FIELD_TYPE.indexOptions() && path == Defaults.PATH - && hasCustomFieldDataSettings == false) { + && hasCustomFieldDataSettings() == false) { return builder; } builder.startObject(CONTENT_TYPE); @@ -330,7 +329,7 @@ public class IdFieldMapper extends AbstractFieldMapper implements RootMapper { builder.field("path", path); } - if (hasCustomFieldDataSettings) { + if (hasCustomFieldDataSettings()) { builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); } else if (includeDefaults) { builder.field("fielddata", (Map) fieldType().fieldDataType().getSettings().getAsMap()); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java index 4c650e3dea7..5f60e1abcc7 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java @@ -206,10 +206,9 @@ public class IndexFieldMapper extends AbstractFieldMapper implements RootMapper @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { boolean includeDefaults = params.paramAsBoolean("include_defaults", false); - boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; // if all defaults, no need to write it at all - if (!includeDefaults && fieldType().stored() == Defaults.FIELD_TYPE.stored() && enabledState == Defaults.ENABLED_STATE && hasCustomFieldDataSettings == false) { + if (!includeDefaults && fieldType().stored() == Defaults.FIELD_TYPE.stored() && enabledState == Defaults.ENABLED_STATE && hasCustomFieldDataSettings() == false) { return builder; } builder.startObject(CONTENT_TYPE); @@ -221,7 +220,7 @@ public class IndexFieldMapper extends AbstractFieldMapper implements RootMapper } if (indexCreatedBefore2x) { - if (hasCustomFieldDataSettings) { + if (hasCustomFieldDataSettings()) { builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); } else if (includeDefaults) { builder.field("fielddata", (Map) fieldType().fieldDataType().getSettings().getAsMap()); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java index bfde40a91c9..29d81a5ed44 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java @@ -324,11 +324,10 @@ public class ParentFieldMapper extends AbstractFieldMapper implements RootMapper return builder; } boolean includeDefaults = params.paramAsBoolean("include_defaults", false); - boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; builder.startObject(CONTENT_TYPE); builder.field("type", type); - if (hasCustomFieldDataSettings) { + if (hasCustomFieldDataSettings()) { builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); } else if (includeDefaults) { builder.field("fielddata", (Map) fieldType().fieldDataType().getSettings().getAsMap()); 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 f6624b600cb..bb55e06b72f 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 @@ -331,10 +331,9 @@ public class TimestampFieldMapper extends DateFieldMapper implements RootMapper boolean includeDefaults = params.paramAsBoolean("include_defaults", false); boolean indexed = fieldType().indexOptions() != IndexOptions.NONE; boolean indexedDefault = Defaults.FIELD_TYPE.indexOptions() != IndexOptions.NONE; - boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; // if all are defaults, no sense to write it at all - if (!includeDefaults && indexed == indexedDefault && hasCustomFieldDataSettings == false && + if (!includeDefaults && indexed == indexedDefault && hasCustomFieldDataSettings() == false && fieldType().stored() == Defaults.FIELD_TYPE.stored() && enabledState == Defaults.ENABLED && path == Defaults.PATH && fieldType().dateTimeFormatter().format().equals(Defaults.DATE_TIME_FORMATTER.format()) && Defaults.DEFAULT_TIMESTAMP.equals(defaultTimestamp) @@ -367,7 +366,7 @@ public class TimestampFieldMapper extends DateFieldMapper implements RootMapper builder.field("ignore_missing", ignoreMissing); } if (indexCreatedBefore2x) { - if (hasCustomFieldDataSettings) { + if (hasCustomFieldDataSettings()) { builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); } else if (includeDefaults) { builder.field("fielddata", (Map) fieldType().fieldDataType().getSettings().getAsMap()); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java index 8690e184c19..8203622444f 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java @@ -219,16 +219,15 @@ public class UidFieldMapper extends AbstractFieldMapper implements RootMapper { return builder; } boolean includeDefaults = params.paramAsBoolean("include_defaults", false); - boolean hasCustomFieldDataSettings = customFieldDataSettings != null && customFieldDataSettings.equals(Settings.EMPTY) == false; // if defaults, don't output - if (!includeDefaults && hasCustomFieldDataSettings == false) { + if (!includeDefaults && hasCustomFieldDataSettings() == false) { return builder; } builder.startObject(CONTENT_TYPE); - if (hasCustomFieldDataSettings) { + if (hasCustomFieldDataSettings()) { builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); } else if (includeDefaults) { builder.field("fielddata", (Map) fieldType().fieldDataType().getSettings().getAsMap()); From 542c25e78dfedaf9666e1f6b30b3dc7db4ed870f Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Tue, 23 Jun 2015 09:53:38 -0700 Subject: [PATCH 5/6] Remove MapperAnalyzer --- .../index/analysis/FieldNameAnalyzer.java | 11 +--- .../index/mapper/MapperAnalyzer.java | 50 -------------- .../index/mapper/MapperService.java | 65 +++++++++++-------- .../elasticsearch/index/shard/IndexShard.java | 9 +-- .../shard/TranslogRecoveryPerformer.java | 6 +- .../index/engine/InternalEngineTests.java | 2 +- .../mapper/merge/TestMergeMapperTests.java | 12 +--- 7 files changed, 47 insertions(+), 108 deletions(-) delete mode 100644 core/src/main/java/org/elasticsearch/index/mapper/MapperAnalyzer.java 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 66002e4ba3e..bea6dfbcd61 100644 --- a/core/src/main/java/org/elasticsearch/index/analysis/FieldNameAnalyzer.java +++ b/core/src/main/java/org/elasticsearch/index/analysis/FieldNameAnalyzer.java @@ -52,20 +52,15 @@ public final class FieldNameAnalyzer extends DelegatingAnalyzerWrapper { return defaultAnalyzer; } - /** NOTE: public so MapperAnalyzer can invoke: */ @Override - public Analyzer getWrappedAnalyzer(String fieldName) { - return getAnalyzer(fieldName); - } - - private Analyzer getAnalyzer(String name) { - Analyzer analyzer = analyzers.get(name); + protected Analyzer getWrappedAnalyzer(String fieldName) { + Analyzer analyzer = analyzers.get(fieldName); if (analyzer != null) { return analyzer; } // Don't be lenient here and return the default analyzer // Fields need to be explicitly added - throw new IllegalArgumentException("Field [" + name + "] has no associated analyzer"); + throw new IllegalArgumentException("Field [" + fieldName + "] has no associated analyzer"); } /** diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MapperAnalyzer.java b/core/src/main/java/org/elasticsearch/index/mapper/MapperAnalyzer.java deleted file mode 100644 index 336d9a3f602..00000000000 --- a/core/src/main/java/org/elasticsearch/index/mapper/MapperAnalyzer.java +++ /dev/null @@ -1,50 +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; - -import org.apache.lucene.analysis.Analyzer; -import org.apache.lucene.analysis.DelegatingAnalyzerWrapper; -import org.elasticsearch.index.analysis.FieldNameAnalyzer; - -/** Hacky analyzer to dispatch per-thread based on the type of the current document being indexed, to look up the per-field Analyzer. Once - * mappings are moved to the index level we can remove this. */ -public class MapperAnalyzer extends DelegatingAnalyzerWrapper { - - private final MapperService mapperService; - - /** Which type this thread is currently indexing. */ - private final ThreadLocal threadTypes = new ThreadLocal<>(); - - public MapperAnalyzer(MapperService mapperService) { - super(Analyzer.PER_FIELD_REUSE_STRATEGY); - this.mapperService = mapperService; - } - - /** Any thread that is about to use this analyzer for indexing must first set the type by calling this. */ - public void setType(String type) { - threadTypes.set(type); - } - - @Override - protected Analyzer getWrappedAnalyzer(String fieldName) { - // First get the FieldNameAnalyzer from the type, then ask it for the right analyzer for this field, or the default index analyzer: - return ((FieldNameAnalyzer) mapperService.documentMapper(threadTypes.get()).mappers().indexAnalyzer()).getWrappedAnalyzer(fieldName); - } -} 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 e7d275f4c70..b1630ed7020 100755 --- a/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java @@ -72,6 +72,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Function; import static org.elasticsearch.common.collect.MapBuilder.newMapBuilder; @@ -85,6 +86,23 @@ public class MapperService extends AbstractIndexComponent { "_uid", "_id", "_type", "_all", "_parent", "_routing", "_index", "_size", "_timestamp", "_ttl" ); + + private static final Function INDEX_ANALYZER_EXTRACTOR = new Function() { + public Analyzer apply(MappedFieldType fieldType) { + return fieldType.indexAnalyzer(); + } + }; + private static final Function SEARCH_ANALYZER_EXTRACTOR = new Function() { + public Analyzer apply(MappedFieldType fieldType) { + return fieldType.searchAnalyzer(); + } + }; + private static final Function SEARCH_QUOTE_ANALYZER_EXTRACTOR = new Function() { + public Analyzer apply(MappedFieldType fieldType) { + return fieldType.searchQuoteAnalyzer(); + } + }; + private final AnalysisService analysisService; private final IndexFieldDataService fieldDataService; @@ -110,8 +128,9 @@ public class MapperService extends AbstractIndexComponent { private final DocumentMapperParser documentParser; - private final SmartIndexNameSearchAnalyzer searchAnalyzer; - private final SmartIndexNameSearchQuoteAnalyzer searchQuoteAnalyzer; + private final MapperAnalyzerWrapper indexAnalyzer; + private final MapperAnalyzerWrapper searchAnalyzer; + private final MapperAnalyzerWrapper searchQuoteAnalyzer; private final List typeListeners = new CopyOnWriteArrayList<>(); @@ -128,8 +147,9 @@ public class MapperService extends AbstractIndexComponent { this.fieldDataService = fieldDataService; this.fieldTypes = new FieldTypeLookup(); this.documentParser = new DocumentMapperParser(index, indexSettings, this, analysisService, similarityLookupService, scriptService); - this.searchAnalyzer = new SmartIndexNameSearchAnalyzer(analysisService.defaultSearchAnalyzer()); - this.searchQuoteAnalyzer = new SmartIndexNameSearchQuoteAnalyzer(analysisService.defaultSearchQuoteAnalyzer()); + this.indexAnalyzer = new MapperAnalyzerWrapper(analysisService.defaultIndexAnalyzer(), INDEX_ANALYZER_EXTRACTOR); + this.searchAnalyzer = new MapperAnalyzerWrapper(analysisService.defaultSearchAnalyzer(), SEARCH_ANALYZER_EXTRACTOR); + this.searchQuoteAnalyzer = new MapperAnalyzerWrapper(analysisService.defaultSearchQuoteAnalyzer(), SEARCH_QUOTE_ANALYZER_EXTRACTOR); this.dynamic = indexSettings.getAsBoolean("index.mapper.dynamic", true); defaultPercolatorMappingSource = "{\n" + @@ -558,6 +578,10 @@ public class MapperService extends AbstractIndexComponent { return fieldType; } + public Analyzer indexAnalyzer() { + return this.indexAnalyzer; + } + public Analyzer searchAnalyzer() { return this.searchAnalyzer; } @@ -604,39 +628,26 @@ public class MapperService extends AbstractIndexComponent { return META_FIELDS.contains(fieldName); } - final class SmartIndexNameSearchAnalyzer extends DelegatingAnalyzerWrapper { + /** An analyzer wrapper that can lookup fields within the index mappings */ + final class MapperAnalyzerWrapper extends DelegatingAnalyzerWrapper { private final Analyzer defaultAnalyzer; + private final Function extractAnalyzer; - SmartIndexNameSearchAnalyzer(Analyzer defaultAnalyzer) { + MapperAnalyzerWrapper(Analyzer defaultAnalyzer, Function extractAnalyzer) { super(Analyzer.PER_FIELD_REUSE_STRATEGY); this.defaultAnalyzer = defaultAnalyzer; + this.extractAnalyzer = extractAnalyzer; } @Override protected Analyzer getWrappedAnalyzer(String fieldName) { MappedFieldType fieldType = smartNameFieldType(fieldName); - if (fieldType != null && fieldType.searchAnalyzer() != null) { - return fieldType.searchAnalyzer(); - } - return defaultAnalyzer; - } - } - - final class SmartIndexNameSearchQuoteAnalyzer extends DelegatingAnalyzerWrapper { - - private final Analyzer defaultAnalyzer; - - SmartIndexNameSearchQuoteAnalyzer(Analyzer defaultAnalyzer) { - super(Analyzer.PER_FIELD_REUSE_STRATEGY); - this.defaultAnalyzer = defaultAnalyzer; - } - - @Override - protected Analyzer getWrappedAnalyzer(String fieldName) { - MappedFieldType fieldType = smartNameFieldType(fieldName); - if (fieldType != null && fieldType.searchQuoteAnalyzer() != null) { - return fieldType.searchQuoteAnalyzer(); + if (fieldType != null) { + Analyzer analyzer = extractAnalyzer.apply(fieldType); + if (analyzer != null) { + return analyzer; + } } return defaultAnalyzer; } diff --git a/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java b/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java index af121a6f707..50295cda652 100644 --- a/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java +++ b/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java @@ -177,8 +177,6 @@ public class IndexShard extends AbstractIndexShardComponent { private final MeanMetric flushMetric = new MeanMetric(); private final ShardEngineFailListener failedEngineListener = new ShardEngineFailListener(); - - private final MapperAnalyzer mapperAnalyzer; private volatile boolean flushOnClose = true; /** @@ -235,7 +233,6 @@ public class IndexShard extends AbstractIndexShardComponent { this.flushOnClose = indexSettings.getAsBoolean(INDEX_FLUSH_ON_CLOSE, true); this.nodeEnv = nodeEnv; indexSettingsService.addListener(applyRefreshSettings); - this.mapperAnalyzer = new MapperAnalyzer(mapperService); this.path = path; this.mergePolicyConfig = new MergePolicyConfig(logger, indexSettings); /* create engine config */ @@ -466,7 +463,6 @@ public class IndexShard extends AbstractIndexShardComponent { public void create(Engine.Create create) { writeAllowed(create.origin()); create = indexingService.preCreate(create); - mapperAnalyzer.setType(create.type()); try { if (logger.isTraceEnabled()) { logger.trace("index [{}][{}]{}", create.type(), create.id(), create.docs()); @@ -505,7 +501,6 @@ public class IndexShard extends AbstractIndexShardComponent { public boolean index(Engine.Index index) { writeAllowed(index.origin()); index = indexingService.preIndex(index); - mapperAnalyzer.setType(index.type()); final boolean created; try { if (logger.isTraceEnabled()) { @@ -1337,7 +1332,7 @@ public class IndexShard extends AbstractIndexShardComponent { } private final EngineConfig newEngineConfig(TranslogConfig translogConfig) { - final TranslogRecoveryPerformer translogRecoveryPerformer = new TranslogRecoveryPerformer(shardId, mapperService, mapperAnalyzer, queryParserService, indexAliasesService, indexCache) { + final TranslogRecoveryPerformer translogRecoveryPerformer = new TranslogRecoveryPerformer(shardId, mapperService, queryParserService, indexAliasesService, indexCache) { @Override protected void operationProcessed() { assert recoveryState != null; @@ -1346,7 +1341,7 @@ public class IndexShard extends AbstractIndexShardComponent { }; return new EngineConfig(shardId, threadPool, indexingService, indexSettingsService, warmer, store, deletionPolicy, mergePolicyConfig.getMergePolicy(), mergeSchedulerConfig, - mapperAnalyzer, similarityService.similarity(), codecService, failedEngineListener, translogRecoveryPerformer, indexCache.filter(), indexCache.filterPolicy(), translogConfig); + mapperService.indexAnalyzer(), similarityService.similarity(), codecService, failedEngineListener, translogRecoveryPerformer, indexCache.filter(), indexCache.filterPolicy(), translogConfig); } private static class IndexShardOperationCounter extends AbstractRefCounted { diff --git a/core/src/main/java/org/elasticsearch/index/shard/TranslogRecoveryPerformer.java b/core/src/main/java/org/elasticsearch/index/shard/TranslogRecoveryPerformer.java index 482515e0b02..4418551bc2f 100644 --- a/core/src/main/java/org/elasticsearch/index/shard/TranslogRecoveryPerformer.java +++ b/core/src/main/java/org/elasticsearch/index/shard/TranslogRecoveryPerformer.java @@ -53,17 +53,15 @@ public class TranslogRecoveryPerformer { private final IndexQueryParserService queryParserService; private final IndexAliasesService indexAliasesService; private final IndexCache indexCache; - private final MapperAnalyzer mapperAnalyzer; private final Map recoveredTypes = new HashMap<>(); private final ShardId shardId; - protected TranslogRecoveryPerformer(ShardId shardId, MapperService mapperService, MapperAnalyzer mapperAnalyzer, IndexQueryParserService queryParserService, IndexAliasesService indexAliasesService, IndexCache indexCache) { + protected TranslogRecoveryPerformer(ShardId shardId, MapperService mapperService, IndexQueryParserService queryParserService, IndexAliasesService indexAliasesService, IndexCache indexCache) { this.shardId = shardId; this.mapperService = mapperService; this.queryParserService = queryParserService; this.indexAliasesService = indexAliasesService; this.indexCache = indexCache; - this.mapperAnalyzer = mapperAnalyzer; } protected Tuple docMapper(String type) { @@ -136,7 +134,6 @@ public class TranslogRecoveryPerformer { source(create.source()).type(create.type()).id(create.id()) .routing(create.routing()).parent(create.parent()).timestamp(create.timestamp()).ttl(create.ttl()), create.version(), create.versionType().versionTypeForReplicationAndRecovery(), Engine.Operation.Origin.RECOVERY, true, false); - mapperAnalyzer.setType(create.type()); // this is a PITA - once mappings are per index not per type this can go away an we can just simply move this to the engine eventually :) maybeAddMappingUpdate(engineCreate.type(), engineCreate.parsedDoc().dynamicMappingsUpdate(), engineCreate.id(), allowMappingUpdates); engine.create(engineCreate); break; @@ -145,7 +142,6 @@ public class TranslogRecoveryPerformer { Engine.Index engineIndex = IndexShard.prepareIndex(docMapper(index.type()), source(index.source()).type(index.type()).id(index.id()) .routing(index.routing()).parent(index.parent()).timestamp(index.timestamp()).ttl(index.ttl()), index.version(), index.versionType().versionTypeForReplicationAndRecovery(), Engine.Operation.Origin.RECOVERY, true); - mapperAnalyzer.setType(index.type()); maybeAddMappingUpdate(engineIndex.type(), engineIndex.parsedDoc().dynamicMappingsUpdate(), engineIndex.id(), allowMappingUpdates); engine.index(engineIndex); break; 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 4ce54abc16e..6371fcf8865 100644 --- a/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java +++ b/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java @@ -1825,7 +1825,7 @@ public class InternalEngineTests extends ElasticsearchTestCase { public final AtomicInteger recoveredOps = new AtomicInteger(0); public TranslogHandler(String indexName) { - super(new ShardId("test", 0), null, new MapperAnalyzer(null), null, null, null); + super(new ShardId("test", 0), null, null, null, null); Settings settings = Settings.settingsBuilder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build(); RootObjectMapper.Builder rootBuilder = new RootObjectMapper.Builder("test"); Index index = new Index(indexName); 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 72ecc503367..bc24670fbf5 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 @@ -45,12 +45,8 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; -/** - * - */ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { - @Test public void test1Merge() throws Exception { String stage1Mapping = XContentFactory.jsonBuilder().startObject().startObject("person").startObject("properties") @@ -79,7 +75,6 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { assertThat(stage1.mappers().smartNameFieldMapper("obj1.prop1"), notNullValue()); } - @Test public void testMergeObjectDynamic() throws Exception { DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); String objectMapping = XContentFactory.jsonBuilder().startObject().startObject("type1").endObject().endObject().string(); @@ -95,7 +90,6 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { assertThat(mapper.root().dynamic(), equalTo(ObjectMapper.Dynamic.FALSE)); } - @Test public void testMergeObjectAndNested() throws Exception { DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); String objectMapping = XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties") @@ -117,7 +111,6 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { assertThat(mergeResult.buildConflicts()[0], equalTo("object mapping [obj] can't be changed from nested to non-nested")); } - @Test public void testMergeSearchAnalyzer() throws Exception { DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); String mapping1 = XContentFactory.jsonBuilder().startObject().startObject("type") @@ -137,7 +130,6 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { assertThat(((NamedAnalyzer) existing.mappers().getMapper("field").fieldType().searchAnalyzer()).name(), equalTo("keyword")); } - @Test public void testChangeSearchAnalyzerToDefault() throws Exception { DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); String mapping1 = XContentFactory.jsonBuilder().startObject().startObject("type") @@ -165,7 +157,7 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { DocumentFieldMappers dfm = documentMapper.mappers(); try { - ((FieldNameAnalyzer) dfm.indexAnalyzer()).getWrappedAnalyzer("non_existing_field"); + assertNotNull(dfm.indexAnalyzer().tokenStream("non_existing_field", "foo")); fail(); } catch (IllegalArgumentException e) { // ok that's expected @@ -207,7 +199,7 @@ public class TestMergeMapperTests extends ElasticsearchSingleNodeTest { continue; } dfm = documentMapper.mappers(); - ((FieldNameAnalyzer) dfm.indexAnalyzer()).getWrappedAnalyzer(fieldName); + assertNotNull(dfm.indexAnalyzer().tokenStream(fieldName, "foo")); } } finally { stopped.set(true); From 573c85251efbfbbf17413fd55786099b29b79253 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Tue, 23 Jun 2015 12:34:49 -0700 Subject: [PATCH 6/6] Added better error message when field types are not the same --- .../index/mapper/FieldTypeLookup.java | 14 +++-- .../index/mapper/MappedFieldType.java | 29 +++++++--- .../mapper/core/AbstractFieldMapper.java | 20 +++---- .../index/mapper/core/BinaryFieldMapper.java | 9 ++-- .../index/mapper/core/BooleanFieldMapper.java | 9 ++-- .../index/mapper/core/ByteFieldMapper.java | 5 ++ .../mapper/core/CompletionFieldMapper.java | 9 ++-- .../index/mapper/core/DateFieldMapper.java | 5 ++ .../index/mapper/core/DoubleFieldMapper.java | 7 ++- .../index/mapper/core/FloatFieldMapper.java | 5 ++ .../index/mapper/core/IntegerFieldMapper.java | 5 ++ .../index/mapper/core/LongFieldMapper.java | 5 ++ .../index/mapper/core/NumberFieldMapper.java | 1 - .../index/mapper/core/ShortFieldMapper.java | 5 ++ .../index/mapper/core/StringFieldMapper.java | 9 ++-- .../index/mapper/geo/GeoPointFieldMapper.java | 9 ++-- .../index/mapper/geo/GeoShapeFieldMapper.java | 9 ++-- .../index/mapper/internal/AllFieldMapper.java | 9 ++-- .../internal/FieldNamesFieldMapper.java | 19 ++++--- .../index/mapper/internal/IdFieldMapper.java | 8 +-- .../mapper/internal/IndexFieldMapper.java | 9 ++-- .../mapper/internal/ParentFieldMapper.java | 9 ++-- .../mapper/internal/RoutingFieldMapper.java | 9 ++-- .../mapper/internal/SourceFieldMapper.java | 9 ++-- .../mapper/internal/TypeFieldMapper.java | 9 ++-- .../index/mapper/internal/UidFieldMapper.java | 9 ++-- .../mapper/internal/VersionFieldMapper.java | 9 ++-- .../index/mapper/ip/IpFieldMapper.java | 5 ++ .../index/mapper/FieldTypeLookupTests.java | 18 ++++++- .../index/mapper/FieldTypeTestCase.java | 53 ++++++++++++++++--- .../index/mapper/MappedFieldTypeTests.java | 27 ---------- .../mapper/externalvalues/ExternalMapper.java | 23 +++++++- .../mapper/geo/GeoPointFieldTypeTests.java | 6 ++- 33 files changed, 270 insertions(+), 116 deletions(-) delete mode 100644 core/src/test/java/org/elasticsearch/index/mapper/MappedFieldTypeTests.java 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 c4eab151a56..7f4d76d0b42 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java @@ -107,9 +107,12 @@ class FieldTypeLookup implements Iterable { for (FieldMapper fieldMapper : newFieldMappers) { MappedFieldTypeReference ref = fullNameToFieldType.get(fieldMapper.fieldType().names().fullName()); if (ref != null) { - boolean strict = ref.getNumAssociatedMappers() > 1 && updateAllTypes == false; List conflicts = new ArrayList<>(); - ref.get().checkCompatibility(fieldMapper.fieldType(), conflicts, strict); + ref.get().checkTypeName(fieldMapper.fieldType(), conflicts); + if (conflicts.isEmpty()) { // only check compat if they are the same type + boolean strict = ref.getNumAssociatedMappers() > 1 && updateAllTypes == false; + 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" + conflicts.toString()); } @@ -118,9 +121,12 @@ class FieldTypeLookup implements Iterable { // field type for the index name must be compatible too MappedFieldTypeReference indexNameRef = fullNameToFieldType.get(fieldMapper.fieldType().names().indexName()); if (indexNameRef != null) { - boolean strict = indexNameRef.getNumAssociatedMappers() > 1 && updateAllTypes == false; List conflicts = new ArrayList<>(); - indexNameRef.get().checkCompatibility(fieldMapper.fieldType(), conflicts, strict); + ref.get().checkTypeName(fieldMapper.fieldType(), conflicts); + if (conflicts.isEmpty()) { // only check compat if they are the same type + boolean strict = indexNameRef.getNumAssociatedMappers() > 1 && updateAllTypes == false; + 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()); } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java index 9480ae83b86..c2af1255fe4 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java @@ -50,7 +50,7 @@ import java.util.Objects; /** * This defines the core properties and functions to operate on a field. */ -public class MappedFieldType extends FieldType { +public abstract class MappedFieldType extends FieldType { public static class Names { @@ -194,12 +194,17 @@ public class MappedFieldType extends FieldType { this.nullValueAsString = ref.nullValueAsString(); } - public MappedFieldType() {} - - public MappedFieldType clone() { - return new MappedFieldType(this); + public MappedFieldType() { + setTokenized(true); + setStored(false); + setStoreTermVectors(false); + setOmitNorms(false); + setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS); + setBoost(1.0f); } + public abstract MappedFieldType clone(); + @Override public boolean equals(Object o) { if (!super.equals(o)) return false; @@ -224,6 +229,18 @@ public class MappedFieldType extends FieldType { // norelease: we need to override freeze() and add safety checks that all settings are actually set + /** Returns the name of this type, as would be specified in mapping properties */ + public abstract String typeName(); + + /** Checks this type is the same type as other. Adds a conflict if they are different. */ + public final void checkTypeName(MappedFieldType other, List conflicts) { + if (typeName().equals(other.typeName()) == false) { + conflicts.add("mapper [" + names().fullName() + "] cannot be changed from type [" + typeName() + "] to [" + other.typeName() + "]"); + } else if (getClass() != other.getClass()) { + throw new IllegalStateException("Type names equal for class " + getClass().getSimpleName() + " and " + other.getClass().getSimpleName()); + } + } + /** * Checks for any conflicts between this field type and other. * If strict is true, all properties must be equal. @@ -240,7 +257,7 @@ public class MappedFieldType extends FieldType { conflicts.add("mapper [" + names().fullName() + "] has different store values"); } if (hasDocValues() == false && other.hasDocValues()) { - // don't add conflict if this mapper has doc values while the mapper to merge doesn't since doc values are implicitely set + // don't add conflict if this mapper has doc values while the mapper to merge doesn't since doc values are implicitly set // when the doc_values field data format is configured conflicts.add("mapper [" + names().fullName() + "] has different doc_values values"); } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java index e60cba25c87..2c6a865ccd9 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/AbstractFieldMapper.java @@ -63,18 +63,6 @@ import static org.elasticsearch.index.mapper.core.TypeParsers.DOC_VALUES; public abstract class AbstractFieldMapper implements FieldMapper { public static class Defaults { - public static final MappedFieldType FIELD_TYPE = new MappedFieldType(); - - static { - FIELD_TYPE.setTokenized(true); - FIELD_TYPE.setStored(false); - FIELD_TYPE.setStoreTermVectors(false); - FIELD_TYPE.setOmitNorms(false); - FIELD_TYPE.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS); - FIELD_TYPE.setBoost(Defaults.BOOST); - FIELD_TYPE.freeze(); - } - public static final float BOOST = 1.0f; public static final ContentPath.Type PATH_TYPE = ContentPath.Type.FULL; } @@ -409,6 +397,14 @@ public abstract class AbstractFieldMapper implements FieldMapper { } AbstractFieldMapper fieldMergeWith = (AbstractFieldMapper) mergeWith; List subConflicts = new ArrayList<>(); // TODO: just expose list from MergeResult? + fieldType().checkTypeName(fieldMergeWith.fieldType(), subConflicts); + if (subConflicts.isEmpty() == false) { + // return early if field types don't match + assert subConflicts.size() == 1; + mergeResult.addConflict(subConflicts.get(0)); + return; + } + boolean strict = this.fieldTypeRef.getNumAssociatedMappers() > 1 && mergeResult.updateAllTypes() == false; fieldType().checkCompatibility(fieldMergeWith.fieldType(), subConflicts, strict); for (String conflict : subConflicts) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/BinaryFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/BinaryFieldMapper.java index 20127b86bab..654c190cda0 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/BinaryFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/BinaryFieldMapper.java @@ -109,9 +109,7 @@ public class BinaryFieldMapper extends AbstractFieldMapper { static final class BinaryFieldType extends MappedFieldType { private boolean tryUncompressing = false; - public BinaryFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public BinaryFieldType() {} protected BinaryFieldType(BinaryFieldType ref) { super(ref); @@ -135,6 +133,11 @@ public class BinaryFieldMapper extends AbstractFieldMapper { return Objects.hash(super.hashCode(), tryUncompressing); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + public boolean tryUncompressing() { return tryUncompressing; } diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/BooleanFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/BooleanFieldMapper.java index 878ed1b89ea..5a76195df2b 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/BooleanFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/BooleanFieldMapper.java @@ -118,9 +118,7 @@ public class BooleanFieldMapper extends AbstractFieldMapper { public static final class BooleanFieldType extends MappedFieldType { - public BooleanFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public BooleanFieldType() {} protected BooleanFieldType(BooleanFieldType ref) { super(ref); @@ -131,6 +129,11 @@ public class BooleanFieldMapper extends AbstractFieldMapper { return new BooleanFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public Boolean nullValue() { return (Boolean)super.nullValue(); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java index 24e4c99e8cd..4448381296f 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java @@ -134,6 +134,11 @@ public class ByteFieldMapper extends NumberFieldMapper { return new ByteFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public Byte nullValue() { return (Byte)super.nullValue(); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/CompletionFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/CompletionFieldMapper.java index ca9dbb28d96..97030ea5f46 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/CompletionFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/CompletionFieldMapper.java @@ -226,9 +226,7 @@ public class CompletionFieldMapper extends AbstractFieldMapper { private AnalyzingCompletionLookupProvider analyzingSuggestLookupProvider; private SortedMap contextMapping = ContextMapping.EMPTY_MAPPING; - public CompletionFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public CompletionFieldType() {} protected CompletionFieldType(CompletionFieldType ref) { super(ref); @@ -242,6 +240,11 @@ public class CompletionFieldMapper extends AbstractFieldMapper { return new CompletionFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public void checkCompatibility(MappedFieldType fieldType, List conflicts, boolean strict) { super.checkCompatibility(fieldType, conflicts, strict); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java index 54950cfe8f9..c7a290ed3bd 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java @@ -251,6 +251,11 @@ public class DateFieldMapper extends NumberFieldMapper { return Objects.hash(super.hashCode(), dateTimeFormatter.format(), timeUnit); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public void checkCompatibility(MappedFieldType fieldType, List conflicts, boolean strict) { super.checkCompatibility(fieldType, conflicts, strict); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java index b11c2f4384d..d0af749156c 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java @@ -126,7 +126,7 @@ public class DoubleFieldMapper extends NumberFieldMapper { } } - static final class DoubleFieldType extends NumberFieldType { + public static final class DoubleFieldType extends NumberFieldType { public DoubleFieldType() { super(NumericType.DOUBLE); @@ -141,6 +141,11 @@ public class DoubleFieldMapper extends NumberFieldMapper { return new DoubleFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public Double nullValue() { return (Double)super.nullValue(); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java index a83902fb18b..9cfaa8b8999 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java @@ -142,6 +142,11 @@ public class FloatFieldMapper extends NumberFieldMapper { return new FloatFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public Float nullValue() { return (Float)super.nullValue(); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java index 147fea564cc..f4958ee2ee0 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java @@ -143,6 +143,11 @@ public class IntegerFieldMapper extends NumberFieldMapper { return new IntegerFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public Integer nullValue() { return (Integer)super.nullValue(); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java index 388450aa01b..18596404c86 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java @@ -142,6 +142,11 @@ public class LongFieldMapper extends NumberFieldMapper { return new LongFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public Long nullValue() { return (Long)super.nullValue(); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java index 070d0d0a001..e9d9896a101 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/NumberFieldMapper.java @@ -136,7 +136,6 @@ public abstract class NumberFieldMapper extends AbstractFieldMapper implements A public static abstract class NumberFieldType extends MappedFieldType { public NumberFieldType(NumericType numericType) { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); setTokenized(false); setOmitNorms(true); setIndexOptions(IndexOptions.DOCS); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java index 61cb08fc56e..8522fd026a5 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java @@ -140,6 +140,11 @@ public class ShortFieldMapper extends NumberFieldMapper { return new ShortFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public Short nullValue() { return (Short)super.nullValue(); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/StringFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/StringFieldMapper.java index 697d1bcd317..0e0b927a550 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/StringFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/StringFieldMapper.java @@ -186,9 +186,7 @@ public class StringFieldMapper extends AbstractFieldMapper implements AllFieldMa public static final class StringFieldType extends MappedFieldType { - public StringFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public StringFieldType() {} protected StringFieldType(StringFieldType ref) { super(ref); @@ -198,6 +196,11 @@ public class StringFieldMapper extends AbstractFieldMapper implements AllFieldMa return new StringFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public String value(Object value) { if (value == null) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoPointFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoPointFieldMapper.java index 85a8a9f78d2..6ca88d63d41 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoPointFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoPointFieldMapper.java @@ -287,9 +287,7 @@ public class GeoPointFieldMapper extends AbstractFieldMapper implements ArrayVal private boolean normalizeLon = true; private boolean normalizeLat = true; - public GeoPointFieldType() { - super(StringFieldMapper.Defaults.FIELD_TYPE); - } + public GeoPointFieldType() {} protected GeoPointFieldType(GeoPointFieldType ref) { super(ref); @@ -328,6 +326,11 @@ public class GeoPointFieldMapper extends AbstractFieldMapper implements ArrayVal public int hashCode() { return java.util.Objects.hash(super.hashCode(), geohashFieldType, geohashPrecision, geohashPrefixEnabled, latFieldType, lonFieldType, validateLon, validateLat, normalizeLon, normalizeLat); } + + @Override + public String typeName() { + return CONTENT_TYPE; + } @Override public void checkCompatibility(MappedFieldType fieldType, List conflicts, boolean strict) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapper.java index f83d0575f34..3a3d568216d 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapper.java @@ -183,9 +183,7 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper { private RecursivePrefixTreeStrategy recursiveStrategy; private TermQueryPrefixTreeStrategy termStrategy; - public GeoShapeFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public GeoShapeFieldType() {} protected GeoShapeFieldType(GeoShapeFieldType ref) { super(ref); @@ -221,6 +219,11 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper { return Objects.hash(super.hashCode(), tree, strategyName, treeLevels, precisionInMeters, distanceErrorPct, defaultDistanceErrorPct, orientation); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public void freeze() { super.freeze(); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java index 68539208fd3..73e495b1558 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/AllFieldMapper.java @@ -156,9 +156,7 @@ public class AllFieldMapper extends AbstractFieldMapper implements RootMapper { static final class AllFieldType extends MappedFieldType { - public AllFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public AllFieldType() {} protected AllFieldType(AllFieldType ref) { super(ref); @@ -169,6 +167,11 @@ public class AllFieldMapper extends AbstractFieldMapper implements RootMapper { return new AllFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public String value(Object value) { if (value == null) { 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 4a6a2b0a4ec..09f970b3e6e 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 @@ -137,15 +137,18 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper implements RootMa private boolean enabled = Defaults.ENABLED; - public FieldNamesFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public FieldNamesFieldType() {} protected FieldNamesFieldType(FieldNamesFieldType ref) { super(ref); this.enabled = ref.enabled; } + @Override + public FieldNamesFieldType clone() { + return new FieldNamesFieldType(this); + } + @Override public boolean equals(Object o) { if (!super.equals(o)) return false; @@ -158,6 +161,11 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper implements RootMa return Objects.hash(super.hashCode(), enabled); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public void checkCompatibility(MappedFieldType fieldType, List conflicts, boolean strict) { if (strict) { @@ -177,11 +185,6 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper implements RootMa return enabled; } - @Override - public FieldNamesFieldType clone() { - return new FieldNamesFieldType(this); - } - @Override public String value(Object value) { if (value == null) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java index 5a6c7e1c121..9a52d50c5a4 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/IdFieldMapper.java @@ -136,9 +136,7 @@ public class IdFieldMapper extends AbstractFieldMapper implements RootMapper { static final class IdFieldType extends MappedFieldType { - public IdFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public IdFieldType() {} protected IdFieldType(IdFieldType ref) { super(ref); @@ -149,6 +147,10 @@ public class IdFieldMapper extends AbstractFieldMapper implements RootMapper { return new IdFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } @Override public String value(Object value) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java index 5f60e1abcc7..f359f5a1ca8 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java @@ -120,9 +120,7 @@ public class IndexFieldMapper extends AbstractFieldMapper implements RootMapper static final class IndexFieldType extends MappedFieldType { - public IndexFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public IndexFieldType() {} protected IndexFieldType(IndexFieldType ref) { super(ref); @@ -133,6 +131,11 @@ public class IndexFieldMapper extends AbstractFieldMapper implements RootMapper return new IndexFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public String value(Object value) { if (value == null) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java index 29d81a5ed44..08de520247a 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/ParentFieldMapper.java @@ -147,9 +147,7 @@ public class ParentFieldMapper extends AbstractFieldMapper implements RootMapper static final class ParentFieldType extends MappedFieldType { - public ParentFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public ParentFieldType() {} protected ParentFieldType(ParentFieldType ref) { super(ref); @@ -160,6 +158,11 @@ public class ParentFieldMapper extends AbstractFieldMapper implements RootMapper return new ParentFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public Uid value(Object value) { if (value == null) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/RoutingFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/RoutingFieldMapper.java index 29368a54d0f..f4e00f9ccf1 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/RoutingFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/RoutingFieldMapper.java @@ -125,9 +125,7 @@ public class RoutingFieldMapper extends AbstractFieldMapper implements RootMappe static final class RoutingFieldType extends MappedFieldType { - public RoutingFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public RoutingFieldType() {} protected RoutingFieldType(RoutingFieldType ref) { super(ref); @@ -138,6 +136,11 @@ public class RoutingFieldMapper extends AbstractFieldMapper implements RootMappe return new RoutingFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public String value(Object value) { if (value == null) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java index 9a831e32cc8..d6c16d291bb 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/SourceFieldMapper.java @@ -200,9 +200,7 @@ public class SourceFieldMapper extends AbstractFieldMapper implements RootMapper static final class SourceFieldType extends MappedFieldType { - public SourceFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public SourceFieldType() {} protected SourceFieldType(SourceFieldType ref) { super(ref); @@ -213,6 +211,11 @@ public class SourceFieldMapper extends AbstractFieldMapper implements RootMapper return new SourceFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public byte[] value(Object value) { if (value == null) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java index beae9cd0bf5..fa84e6f4cbe 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/TypeFieldMapper.java @@ -106,9 +106,7 @@ public class TypeFieldMapper extends AbstractFieldMapper implements RootMapper { static final class TypeFieldType extends MappedFieldType { - public TypeFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public TypeFieldType() {} protected TypeFieldType(TypeFieldType ref) { super(ref); @@ -119,6 +117,11 @@ public class TypeFieldMapper extends AbstractFieldMapper implements RootMapper { return new TypeFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public String value(Object value) { if (value == null) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java index 8203622444f..d030fcc7f6c 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/UidFieldMapper.java @@ -107,9 +107,7 @@ public class UidFieldMapper extends AbstractFieldMapper implements RootMapper { static final class UidFieldType extends MappedFieldType { - public UidFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public UidFieldType() {} protected UidFieldType(UidFieldType ref) { super(ref); @@ -120,6 +118,11 @@ public class UidFieldMapper extends AbstractFieldMapper implements RootMapper { return new UidFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public Uid value(Object value) { if (value == null) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/VersionFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/VersionFieldMapper.java index 6dc793c383f..327ef7aebcd 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/VersionFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/VersionFieldMapper.java @@ -90,9 +90,7 @@ public class VersionFieldMapper extends AbstractFieldMapper implements RootMappe static final class VersionFieldType extends MappedFieldType { - public VersionFieldType() { - super(AbstractFieldMapper.Defaults.FIELD_TYPE); - } + public VersionFieldType() {} protected VersionFieldType(VersionFieldType ref) { super(ref); @@ -103,6 +101,11 @@ public class VersionFieldMapper extends AbstractFieldMapper implements RootMappe return new VersionFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public Long value(Object value) { if (value == null || (value instanceof Long)) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java index 54218fa1ecb..5874fcc180e 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java @@ -173,6 +173,11 @@ public class IpFieldMapper extends NumberFieldMapper { return new IpFieldType(this); } + @Override + public String typeName() { + return CONTENT_TYPE; + } + @Override public Long value(Object value) { if (value == null) { 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 c5885ba019c..933eb14f7de 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java @@ -175,17 +175,31 @@ public class FieldTypeLookupTests extends ElasticsearchTestCase { return Lists.newArrayList(mapper); } - // this sucks how much must be overriden just do get a dummy field mapper... + // this sucks how much must be overridden just do get a dummy field mapper... static class FakeFieldMapper extends AbstractFieldMapper { static Settings dummySettings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT.id).build(); public FakeFieldMapper(String fullName, String indexName) { super(makeFieldType(fullName, indexName), null, null, dummySettings, null, null); } static MappedFieldType makeFieldType(String fullName, String indexName) { - MappedFieldType fieldType = Defaults.FIELD_TYPE.clone(); + FakeFieldType fieldType = new FakeFieldType(); fieldType.setNames(new MappedFieldType.Names(fullName, indexName, indexName, fullName)); return fieldType; } + static class FakeFieldType extends MappedFieldType { + public FakeFieldType() {} + protected FakeFieldType(FakeFieldType ref) { + super(ref); + } + @Override + public MappedFieldType clone() { + return new FakeFieldType(this); + } + @Override + public String typeName() { + return "faketype"; + } + } @Override public MappedFieldType defaultFieldType() { return null; } @Override diff --git a/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeTestCase.java b/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeTestCase.java index 0dba5b58818..4d7e9c7137e 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeTestCase.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeTestCase.java @@ -24,12 +24,21 @@ import org.elasticsearch.index.fielddata.FieldDataType; import org.elasticsearch.index.similarity.BM25SimilarityProvider; import org.elasticsearch.test.ElasticsearchTestCase; +import java.util.ArrayList; +import java.util.List; + /** Base test case for subclasses of MappedFieldType */ public abstract class FieldTypeTestCase extends ElasticsearchTestCase { /** Create a default constructed fieldtype */ protected abstract MappedFieldType createDefaultFieldType(); + MappedFieldType createNamedDefaultFieldType(String name) { + MappedFieldType fieldType = createDefaultFieldType(); + fieldType.setNames(new MappedFieldType.Names(name)); + return fieldType; + } + /** A dummy null value to use when modifying null value */ protected Object dummyNullValue() { return "dummyvalue"; @@ -79,7 +88,7 @@ public abstract class FieldTypeTestCase extends ElasticsearchTestCase { } public void testClone() { - MappedFieldType fieldType = createDefaultFieldType(); + MappedFieldType fieldType = createNamedDefaultFieldType("foo"); MappedFieldType clone = fieldType.clone(); assertNotSame(clone, fieldType); assertEquals(clone.getClass(), fieldType.getClass()); @@ -87,7 +96,7 @@ public abstract class FieldTypeTestCase extends ElasticsearchTestCase { assertEquals(clone, clone.clone()); // transitivity for (int i = 0; i < numProperties(); ++i) { - fieldType = createDefaultFieldType(); + fieldType = createNamedDefaultFieldType("foo"); modifyProperty(fieldType, i); clone = fieldType.clone(); assertNotSame(clone, fieldType); @@ -96,15 +105,15 @@ public abstract class FieldTypeTestCase extends ElasticsearchTestCase { } public void testEquals() { - MappedFieldType ft1 = createDefaultFieldType(); - MappedFieldType ft2 = createDefaultFieldType(); + MappedFieldType ft1 = createNamedDefaultFieldType("foo"); + MappedFieldType ft2 = createNamedDefaultFieldType("foo"); assertEquals(ft1, ft1); // reflexive assertEquals(ft1, ft2); // symmetric assertEquals(ft2, ft1); assertEquals(ft1.hashCode(), ft2.hashCode()); for (int i = 0; i < numProperties(); ++i) { - ft2 = createDefaultFieldType(); + ft2 = createNamedDefaultFieldType("foo"); modifyProperty(ft2, i); assertNotEquals(ft1, ft2); assertNotEquals(ft1.hashCode(), ft2.hashCode()); @@ -113,7 +122,7 @@ public abstract class FieldTypeTestCase extends ElasticsearchTestCase { public void testFreeze() { for (int i = 0; i < numProperties(); ++i) { - MappedFieldType fieldType = createDefaultFieldType(); + MappedFieldType fieldType = createNamedDefaultFieldType("foo"); fieldType.freeze(); try { modifyProperty(fieldType, i); @@ -123,4 +132,36 @@ public abstract class FieldTypeTestCase extends ElasticsearchTestCase { } } } + + public void testCheckTypeName() { + final MappedFieldType fieldType = createNamedDefaultFieldType("foo"); + List conflicts = new ArrayList<>(); + fieldType.checkTypeName(fieldType, conflicts); + assertTrue(conflicts.toString(), conflicts.isEmpty()); + + MappedFieldType bogus = new MappedFieldType() { + @Override + public MappedFieldType clone() {return null;} + @Override + public String typeName() { return fieldType.typeName();} + }; + try { + fieldType.checkTypeName(bogus, conflicts); + fail("expected bad types exception"); + } catch (IllegalStateException e) { + assertTrue(e.getMessage().contains("Type names equal")); + } + assertTrue(conflicts.toString(), conflicts.isEmpty()); + + MappedFieldType other = new MappedFieldType() { + @Override + public MappedFieldType clone() {return null;} + @Override + public String typeName() { return "othertype";} + }; + fieldType.checkTypeName(other, conflicts); + assertFalse(conflicts.isEmpty()); + assertTrue(conflicts.get(0).contains("cannot be changed from type")); + assertEquals(1, conflicts.size()); + } } diff --git a/core/src/test/java/org/elasticsearch/index/mapper/MappedFieldTypeTests.java b/core/src/test/java/org/elasticsearch/index/mapper/MappedFieldTypeTests.java deleted file mode 100644 index 6cdc809ca23..00000000000 --- a/core/src/test/java/org/elasticsearch/index/mapper/MappedFieldTypeTests.java +++ /dev/null @@ -1,27 +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; - -public class MappedFieldTypeTests extends FieldTypeTestCase { - - @Override - public MappedFieldType createDefaultFieldType() { - return new MappedFieldType(); - } -} 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 45c6322f359..9de34988360 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 @@ -80,7 +80,7 @@ public class ExternalMapper extends AbstractFieldMapper { private String mapperName; public Builder(String name, String generatedValue, String mapperName) { - super(name, Defaults.FIELD_TYPE); + super(name, new ExternalFieldType()); this.builder = this; this.stringBuilder = stringField(name).store(false); this.generatedValue = generatedValue; @@ -142,6 +142,25 @@ public class ExternalMapper extends AbstractFieldMapper { } } + static class ExternalFieldType extends MappedFieldType { + + public ExternalFieldType() {} + + protected ExternalFieldType(ExternalFieldType ref) { + super(ref); + } + + @Override + public MappedFieldType clone() { + return new ExternalFieldType(this); + } + + @Override + public String typeName() { + return "faketype"; + } + } + private final String generatedValue; private final String mapperName; @@ -168,7 +187,7 @@ public class ExternalMapper extends AbstractFieldMapper { @Override public MappedFieldType defaultFieldType() { - return Defaults.FIELD_TYPE; + return new ExternalFieldType(); } @Override diff --git a/core/src/test/java/org/elasticsearch/index/mapper/geo/GeoPointFieldTypeTests.java b/core/src/test/java/org/elasticsearch/index/mapper/geo/GeoPointFieldTypeTests.java index 71f6f88d9aa..8254e0b8bec 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/geo/GeoPointFieldTypeTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/geo/GeoPointFieldTypeTests.java @@ -20,6 +20,8 @@ package org.elasticsearch.index.mapper.geo; import org.elasticsearch.index.mapper.FieldTypeTestCase; import org.elasticsearch.index.mapper.MappedFieldType; +import org.elasticsearch.index.mapper.core.DoubleFieldMapper; +import org.elasticsearch.index.mapper.core.StringFieldMapper; public class GeoPointFieldTypeTests extends FieldTypeTestCase { @Override @@ -36,8 +38,8 @@ public class GeoPointFieldTypeTests extends FieldTypeTestCase { protected void modifyProperty(MappedFieldType ft, int propNum) { GeoPointFieldMapper.GeoPointFieldType gft = (GeoPointFieldMapper.GeoPointFieldType)ft; switch (propNum) { - case 0: gft.setGeohashEnabled(new MappedFieldType(), 1, true); break; - case 1: gft.setLatLonEnabled(new MappedFieldType(), new MappedFieldType()); break; + case 0: gft.setGeohashEnabled(new StringFieldMapper.StringFieldType(), 1, true); break; + case 1: gft.setLatLonEnabled(new DoubleFieldMapper.DoubleFieldType(), new DoubleFieldMapper.DoubleFieldType()); break; case 2: gft.setValidateLon(!gft.validateLon()); break; case 3: gft.setValidateLat(!gft.validateLat()); break; case 4: gft.setNormalizeLon(!gft.normalizeLon()); break;