diff --git a/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java b/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java index de5f058d74f76..2a76d4e97831a 100644 --- a/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java +++ b/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java @@ -537,7 +537,7 @@ public ClusterState execute(final ClusterState currentState) throws Exception { // _default_ types do not go through merging, but we do test the new settings. Also don't apply the old default newMapper = indexService.mapperService().parse(request.type(), new CompressedString(request.source()), false); } else { - newMapper = indexService.mapperService().parse(request.type(), new CompressedString(request.source())); + newMapper = indexService.mapperService().parse(request.type(), new CompressedString(request.source()), existingMapper == null); if (existingMapper != null) { // first, simulate DocumentMapper.MergeResult mergeResult = existingMapper.merge(newMapper, mergeFlags().simulate(true)); diff --git a/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java b/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java index b0340311d9fab..ebeeafd3b7b25 100644 --- a/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java @@ -378,6 +378,10 @@ public T rootMapper(Class type) { return (T) rootMappers.get(type); } + public IndexFieldMapper indexMapper() { + return rootMapper(IndexFieldMapper.class); + } + public TypeFieldMapper typeMapper() { return rootMapper(TypeFieldMapper.class); } @@ -402,6 +406,10 @@ public ParentFieldMapper parentFieldMapper() { return rootMapper(ParentFieldMapper.class); } + public SizeFieldMapper sizeFieldMapper() { + return rootMapper(SizeFieldMapper.class); + } + public TimestampFieldMapper timestampFieldMapper() { return rootMapper(TimestampFieldMapper.class); } diff --git a/src/main/java/org/elasticsearch/index/mapper/MapperService.java b/src/main/java/org/elasticsearch/index/mapper/MapperService.java index 521e02d023e1f..dd38518cab283 100755 --- a/src/main/java/org/elasticsearch/index/mapper/MapperService.java +++ b/src/main/java/org/elasticsearch/index/mapper/MapperService.java @@ -370,13 +370,6 @@ private void removeObjectAndFieldMappers(DocumentMapper docMapper) { } } - /** - * Just parses and returns the mapper without adding it, while still applying default mapping. - */ - public DocumentMapper parse(String mappingType, CompressedString mappingSource) throws MapperParsingException { - return parse(mappingType, mappingSource, true); - } - public DocumentMapper parse(String mappingType, CompressedString mappingSource, boolean applyDefault) throws MapperParsingException { String defaultMappingSource; if (PercolatorService.TYPE_NAME.equals(mappingType)) { diff --git a/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java index cbcdfd80c930d..215c260b23b11 100644 --- a/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java @@ -195,14 +195,14 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws boolean includeDefaults = params.paramAsBoolean("include_defaults", false); // if all defaults, no need to write it at all - if (!includeDefaults && fieldType().stored() == Defaults.FIELD_TYPE.stored() && enabledState == Defaults.ENABLED_STATE) { + if (!includeDefaults && fieldType().stored() == Defaults.FIELD_TYPE.stored() && enabledState == Defaults.ENABLED_STATE && customFieldDataSettings == null) { return builder; } builder.startObject(CONTENT_TYPE); - if (includeDefaults || fieldType().stored() != Defaults.FIELD_TYPE.stored() && enabledState.enabled) { + if (includeDefaults || fieldType().stored() != Defaults.FIELD_TYPE.stored()) { builder.field("store", fieldType().stored()); } - if (includeDefaults || enabledState.enabled != Defaults.ENABLED_STATE.enabled) { + if (includeDefaults || enabledState != Defaults.ENABLED_STATE) { builder.field("enabled", enabledState.enabled); } diff --git a/src/main/java/org/elasticsearch/index/mapper/internal/SizeFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/internal/SizeFieldMapper.java index 74ba6d694dcdb..cab525252dc53 100644 --- a/src/main/java/org/elasticsearch/index/mapper/internal/SizeFieldMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/internal/SizeFieldMapper.java @@ -161,10 +161,10 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws return builder; } builder.startObject(contentType()); - if (includeDefaults || enabledState.enabled != Defaults.ENABLED_STATE.enabled) { + if (includeDefaults || enabledState != Defaults.ENABLED_STATE) { builder.field("enabled", enabledState.enabled); } - if (includeDefaults || fieldType().stored() != Defaults.SIZE_FIELD_TYPE.stored() && enabledState.enabled) { + if (includeDefaults || fieldType().stored() != Defaults.SIZE_FIELD_TYPE.stored()) { builder.field("store", fieldType().stored()); } builder.endObject(); diff --git a/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java index 7ecdc133de394..c3495e3e1daa4 100644 --- a/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/internal/TimestampFieldMapper.java @@ -230,29 +230,27 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws return builder; } builder.startObject(CONTENT_TYPE); - if (includeDefaults || enabledState.enabled != Defaults.ENABLED.enabled) { + if (includeDefaults || enabledState != Defaults.ENABLED) { builder.field("enabled", enabledState.enabled); } - if (enabledState.enabled) { - if (includeDefaults || fieldType.indexed() != Defaults.FIELD_TYPE.indexed()) { - builder.field("index", indexTokenizeOptionToString(fieldType.indexed(), fieldType.tokenized())); - } - if (includeDefaults || fieldType.stored() != Defaults.FIELD_TYPE.stored()) { - builder.field("store", fieldType.stored()); - } - if (includeDefaults || path != Defaults.PATH) { - builder.field("path", path); - } - if (includeDefaults || !dateTimeFormatter.format().equals(Defaults.DATE_TIME_FORMATTER.format())) { - builder.field("format", dateTimeFormatter.format()); - } - if (customFieldDataSettings != null) { - builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); - } else if (includeDefaults) { - builder.field("fielddata", (Map) fieldDataType.getSettings().getAsMap()); - } - + if (includeDefaults || fieldType.indexed() != Defaults.FIELD_TYPE.indexed()) { + builder.field("index", indexTokenizeOptionToString(fieldType.indexed(), fieldType.tokenized())); + } + if (includeDefaults || fieldType.stored() != Defaults.FIELD_TYPE.stored()) { + builder.field("store", fieldType.stored()); + } + if (includeDefaults || path != Defaults.PATH) { + builder.field("path", path); } + if (includeDefaults || !dateTimeFormatter.format().equals(Defaults.DATE_TIME_FORMATTER.format())) { + builder.field("format", dateTimeFormatter.format()); + } + if (customFieldDataSettings != null) { + builder.field("fielddata", (Map) customFieldDataSettings.getAsMap()); + } else if (includeDefaults) { + builder.field("fielddata", (Map) fieldDataType.getSettings().getAsMap()); + } + builder.endObject(); return builder; } diff --git a/src/test/java/org/elasticsearch/index/mapper/index/IndexTypeMapperTests.java b/src/test/java/org/elasticsearch/index/mapper/index/IndexTypeMapperTests.java index ce08da5d81e21..81b56e737e2dc 100644 --- a/src/test/java/org/elasticsearch/index/mapper/index/IndexTypeMapperTests.java +++ b/src/test/java/org/elasticsearch/index/mapper/index/IndexTypeMapperTests.java @@ -21,9 +21,11 @@ import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.mapper.DocumentMapper; +import org.elasticsearch.index.mapper.DocumentMapperParser; import org.elasticsearch.index.mapper.MapperTestUtils; import org.elasticsearch.index.mapper.ParsedDocument; import org.elasticsearch.index.mapper.internal.IndexFieldMapper; +import org.elasticsearch.test.ElasticsearchSingleNodeTest; import org.elasticsearch.test.ElasticsearchTestCase; import org.junit.Test; @@ -33,7 +35,7 @@ /** * */ -public class IndexTypeMapperTests extends ElasticsearchTestCase { +public class IndexTypeMapperTests extends ElasticsearchSingleNodeTest { @Test public void simpleIndexMapperTests() throws Exception { @@ -111,4 +113,21 @@ public void testThatMergingFieldMappingAllowsDisabling() throws Exception { mapperEnabled.merge(mapperDisabled, DocumentMapper.MergeFlags.mergeFlags().simulate(false)); assertThat(mapperEnabled.IndexFieldMapper().enabled(), is(false)); } + + @Test + public void testThatDisablingWorksWhenMerging() throws Exception { + String enabledMapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_index").field("enabled", true).endObject() + .endObject().endObject().string(); + DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser(); + DocumentMapper enabledMapper = parser.parse(enabledMapping); + + String disabledMapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("_index").field("enabled", false).endObject() + .endObject().endObject().string(); + DocumentMapper disabledMapper = parser.parse(disabledMapping); + + enabledMapper.merge(disabledMapper, DocumentMapper.MergeFlags.mergeFlags().simulate(false)); + assertThat(enabledMapper.indexMapper().enabled(), is(false)); + } } diff --git a/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingIntegrationTests.java b/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingIntegrationTests.java index 51239fa2b9118..55e763065af89 100644 --- a/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingIntegrationTests.java +++ b/src/test/java/org/elasticsearch/index/mapper/size/SizeMappingIntegrationTests.java @@ -43,25 +43,44 @@ public void testThatUpdatingMappingShouldNotRemoveSizeMappingConfiguration() thr assertAcked(client().admin().indices().prepareCreate(index).addMapping(type, builder)); // check mapping again - assertSizeMappingEnabled(index, type); + assertSizeMappingEnabled(index, type, true); // update some field in the mapping XContentBuilder updateMappingBuilder = jsonBuilder().startObject().startObject("properties").startObject("otherField").field("type", "string").endObject().endObject(); PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping(index).setType(type).setSource(updateMappingBuilder).get(); assertAcked(putMappingResponse); - // make sure timestamp field is still in mapping - assertSizeMappingEnabled(index, type); + // make sure size field is still in mapping + assertSizeMappingEnabled(index, type, true); } - private void assertSizeMappingEnabled(String index, String type) throws IOException { - String errMsg = String.format(Locale.ROOT, "Expected size field mapping to be enabled for %s/%s", index, type); + @Test + public void testThatSizeCanBeSwitchedOnAndOff() throws Exception { + String index = "foo"; + String type = "mytype"; + + XContentBuilder builder = jsonBuilder().startObject().startObject("_size").field("enabled", true).endObject().endObject(); + assertAcked(client().admin().indices().prepareCreate(index).addMapping(type, builder)); + + // check mapping again + assertSizeMappingEnabled(index, type, true); + + // update some field in the mapping + XContentBuilder updateMappingBuilder = jsonBuilder().startObject().startObject("_size").field("enabled", false).endObject().endObject(); + PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping(index).setType(type).setSource(updateMappingBuilder).get(); + assertAcked(putMappingResponse); + + // make sure size field is still in mapping + assertSizeMappingEnabled(index, type, false); + } + private void assertSizeMappingEnabled(String index, String type, boolean enabled) throws IOException { + String errMsg = String.format(Locale.ROOT, "Expected size field mapping to be " + (enabled ? "enabled" : "disabled") + " for %s/%s", index, type); GetMappingsResponse getMappingsResponse = client().admin().indices().prepareGetMappings(index).addTypes(type).get(); Map mappingSource = getMappingsResponse.getMappings().get(index).get(type).getSourceAsMap(); assertThat(errMsg, mappingSource, hasKey("_size")); - String ttlAsString = mappingSource.get("_size").toString(); - assertThat(ttlAsString, is(notNullValue())); - assertThat(errMsg, ttlAsString, is("{enabled=true}")); + String sizeAsString = mappingSource.get("_size").toString(); + assertThat(sizeAsString, is(notNullValue())); + assertThat(errMsg, sizeAsString, is("{enabled=" + (enabled) + "}")); } } diff --git a/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java b/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java index 2a21f48d7abe9..f2cb7a4444d45 100644 --- a/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java +++ b/src/test/java/org/elasticsearch/index/mapper/source/DefaultSourceMappingTests.java @@ -23,20 +23,25 @@ import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.compress.CompressedString; import org.elasticsearch.common.compress.CompressorFactory; +import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.mapper.*; -import org.elasticsearch.test.ElasticsearchTestCase; +import org.elasticsearch.test.ElasticsearchSingleNodeTest; +import org.elasticsearch.index.service.IndexService; import org.junit.Test; +import java.util.Arrays; +import java.util.List; import java.util.Map; -import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.*; /** * */ -public class DefaultSourceMappingTests extends ElasticsearchTestCase { +public class DefaultSourceMappingTests extends ElasticsearchSingleNodeTest { @Test public void testNoFormat() throws Exception { @@ -199,4 +204,66 @@ public void testDefaultMappingAndWithMappingOverrideWithMapperService() throws E assertThat(mapper.type(), equalTo("my_type")); assertThat(mapper.sourceMapper().enabled(), equalTo(true)); } + + @Test + public void testParsingWithDefaultAppliedAndNotApplied() throws Exception { + String defaultMapping = XContentFactory.jsonBuilder().startObject().startObject(MapperService.DEFAULT_MAPPING) + .startObject("_source").array("includes", "default_field_path.").endObject() + .endObject().endObject().string(); + + MapperService mapperService = createIndex("test").mapperService(); + mapperService.merge(MapperService.DEFAULT_MAPPING, new CompressedString(defaultMapping), true); + + String mapping = XContentFactory.jsonBuilder().startObject().startObject("my_type") + .startObject("_source").array("includes", "custom_field_path.").endObject() + .endObject().endObject().string(); + mapperService.merge("my_type", new CompressedString(mapping), true); + DocumentMapper mapper = mapperService.documentMapper("my_type"); + assertThat(mapper.type(), equalTo("my_type")); + assertThat(mapper.sourceMapper().includes().length, equalTo(2)); + assertThat(mapper.sourceMapper().includes(), hasItemInArray("default_field_path.")); + assertThat(mapper.sourceMapper().includes(), hasItemInArray("custom_field_path.")); + + mapping = XContentFactory.jsonBuilder().startObject().startObject("my_type") + .startObject("properties").startObject("text").field("type", "string").endObject().endObject() + .endObject().endObject().string(); + mapperService.merge("my_type", new CompressedString(mapping), false); + mapper = mapperService.documentMapper("my_type"); + assertThat(mapper.type(), equalTo("my_type")); + assertThat(mapper.sourceMapper().includes(), hasItemInArray("default_field_path.")); + assertThat(mapper.sourceMapper().includes(), hasItemInArray("custom_field_path.")); + assertThat(mapper.sourceMapper().includes().length, equalTo(2)); + } + + public void testDefaultNotAppliedOnUpdate() throws Exception { + XContentBuilder defaultMapping = XContentFactory.jsonBuilder().startObject().startObject(MapperService.DEFAULT_MAPPING) + .startObject("_source").array("includes", "default_field_path.").endObject() + .endObject().endObject(); + + IndexService indexService = createIndex("test", ImmutableSettings.EMPTY, MapperService.DEFAULT_MAPPING, defaultMapping); + + String mapping = XContentFactory.jsonBuilder().startObject().startObject("my_type") + .startObject("_source").array("includes", "custom_field_path.").endObject() + .endObject().endObject().string(); + client().admin().indices().preparePutMapping("test").setType("my_type").setSource(mapping).get(); + + DocumentMapper mapper = indexService.mapperService().documentMapper("my_type"); + assertThat(mapper.type(), equalTo("my_type")); + assertThat(mapper.sourceMapper().includes().length, equalTo(2)); + List includes = Arrays.asList(mapper.sourceMapper().includes()); + assertThat("default_field_path.", isIn(includes)); + assertThat("custom_field_path.", isIn(includes)); + + mapping = XContentFactory.jsonBuilder().startObject().startObject("my_type") + .startObject("properties").startObject("text").field("type", "string").endObject().endObject() + .endObject().endObject().string(); + client().admin().indices().preparePutMapping("test").setType("my_type").setSource(mapping).get(); + + mapper = indexService.mapperService().documentMapper("my_type"); + assertThat(mapper.type(), equalTo("my_type")); + includes = Arrays.asList(mapper.sourceMapper().includes()); + assertThat("default_field_path.", isIn(includes)); + assertThat("custom_field_path.", isIn(includes)); + assertThat(mapper.sourceMapper().includes().length, equalTo(2)); + } } diff --git a/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java b/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java index 4cac4ce88e970..9bddd8964f96e 100644 --- a/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java +++ b/src/test/java/org/elasticsearch/index/mapper/timestamp/TimestampMappingTests.java @@ -118,22 +118,6 @@ public void testThatDisablingDuringMergeIsWorking() throws Exception { assertThat(enabledMapper.timestampFieldMapper().enabled(), is(false)); } - @Test - public void testThatDisablingFieldMapperDoesNotReturnAnyUselessInfo() throws Exception { - boolean inversedStoreSetting = !TimestampFieldMapper.Defaults.FIELD_TYPE.stored(); - String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") - .startObject("_timestamp").field("enabled", false).field("store", inversedStoreSetting).endObject() - .endObject().endObject().string(); - - DocumentMapper mapper = MapperTestUtils.newParser().parse(mapping); - - XContentBuilder builder = XContentFactory.jsonBuilder().startObject(); - mapper.timestampFieldMapper().toXContent(builder, ToXContent.EMPTY_PARAMS); - builder.endObject(); - - assertThat(builder.string(), is(String.format(Locale.ROOT, "{\"%s\":{}}", TimestampFieldMapper.NAME))); - } - @Test // issue 3174 public void testThatSerializationWorksCorrectlyForIndexField() throws Exception { String enabledMapping = XContentFactory.jsonBuilder().startObject().startObject("type") @@ -153,4 +137,4 @@ public void testThatSerializationWorksCorrectlyForIndexField() throws Exception assertThat(timestampConfiguration, hasKey("index")); assertThat(timestampConfiguration.get("index").toString(), is("no")); } -} \ No newline at end of file +} diff --git a/src/test/java/org/elasticsearch/index/mapper/update/UpdateMappingOnCusterTests.java b/src/test/java/org/elasticsearch/index/mapper/update/UpdateMappingOnCusterTests.java new file mode 100644 index 0000000000000..ddf0bf86347b3 --- /dev/null +++ b/src/test/java/org/elasticsearch/index/mapper/update/UpdateMappingOnCusterTests.java @@ -0,0 +1,60 @@ +/* + * 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.update; + +import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.index.mapper.MapperParsingException; +import org.elasticsearch.index.mapper.MergeMappingException; +import org.elasticsearch.test.ElasticsearchIntegrationTest; +import org.junit.Test; + +import static org.elasticsearch.common.io.Streams.copyToStringFromClasspath; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; + + +public class UpdateMappingOnCusterTests extends ElasticsearchIntegrationTest { + + private static final String INDEX = "index"; + private static final String TYPE = "type"; + + // checks if the setting for timestamp and size are kept even if disabled + @Test + public void testDisabledSizeTimestampIndexDoNotLooseMappings() throws Exception { + String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/update/default_mapping_with_disabled_root_types.json"); + prepareCreate(INDEX).addMapping(TYPE, mapping).get(); + GetMappingsResponse mappingsBeforeGreen = client().admin().indices().prepareGetMappings(INDEX).addTypes(TYPE).get(); + ensureGreen(INDEX); + // make sure all nodes have same cluster state + compareMappingOnNodes(mappingsBeforeGreen); + } + + private void compareMappingOnNodes(GetMappingsResponse previousMapping) { + // make sure all nodes have same cluster state + for (Client client : cluster()) { + GetMappingsResponse currentMapping = client.admin().indices().prepareGetMappings(INDEX).addTypes(TYPE).setLocal(true).get(); + assertThat(previousMapping.getMappings().get(INDEX).get(TYPE).source(), equalTo(currentMapping.getMappings().get(INDEX).get(TYPE).source())); + } + } +} diff --git a/src/test/java/org/elasticsearch/index/mapper/update/UpdateMappingTests.java b/src/test/java/org/elasticsearch/index/mapper/update/UpdateMappingTests.java new file mode 100644 index 0000000000000..e48971e359200 --- /dev/null +++ b/src/test/java/org/elasticsearch/index/mapper/update/UpdateMappingTests.java @@ -0,0 +1,148 @@ +/* + * 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.update; + +import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse; +import org.elasticsearch.common.compress.CompressedString; +import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.index.mapper.DocumentMapper; +import org.elasticsearch.index.mapper.MapperService; +import org.elasticsearch.index.service.IndexService; +import org.elasticsearch.test.ElasticsearchSingleNodeTest; +import org.junit.Test; + +import java.io.IOException; +import java.util.LinkedHashMap; + +import static org.elasticsearch.common.io.Streams.copyToStringFromClasspath; +import static org.hamcrest.CoreMatchers.equalTo; + + +public class UpdateMappingTests extends ElasticsearchSingleNodeTest { + + @Test + public void testIndexFieldParsing() throws IOException { + IndexService indexService = createIndex("test", ImmutableSettings.settingsBuilder().build()); + XContentBuilder indexMapping = XContentFactory.jsonBuilder(); + boolean enabled = randomBoolean(); + indexMapping.startObject() + .startObject("type") + .startObject("_index") + .field("enabled", enabled) + .field("store", true) + .startObject("fielddata") + .field("format", "fst") + .endObject() + .endObject() + .endObject() + .endObject(); + DocumentMapper documentMapper = indexService.mapperService().parse("type", new CompressedString(indexMapping.string()), true); + assertThat(documentMapper.indexMapper().enabled(), equalTo(enabled)); + assertTrue(documentMapper.indexMapper().fieldType().stored()); + assertThat(documentMapper.indexMapper().fieldDataType().getFormat(null), equalTo("fst")); + documentMapper.refreshSource(); + documentMapper = indexService.mapperService().parse("type", new CompressedString(documentMapper.mappingSource().string()), true); + assertThat(documentMapper.indexMapper().enabled(), equalTo(enabled)); + assertTrue(documentMapper.indexMapper().fieldType().stored()); + assertThat(documentMapper.indexMapper().fieldDataType().getFormat(null), equalTo("fst")); + } + + @Test + public void testTimestampParsing() throws IOException { + IndexService indexService = createIndex("test", ImmutableSettings.settingsBuilder().build()); + XContentBuilder indexMapping = XContentFactory.jsonBuilder(); + boolean enabled = randomBoolean(); + indexMapping.startObject() + .startObject("type") + .startObject("_timestamp") + .field("enabled", enabled) + .field("store", true) + .startObject("fielddata") + .field("format", "doc_values") + .endObject() + .endObject() + .endObject() + .endObject(); + DocumentMapper documentMapper = indexService.mapperService().parse("type", new CompressedString(indexMapping.string()), true); + assertThat(documentMapper.timestampFieldMapper().enabled(), equalTo(enabled)); + assertTrue(documentMapper.timestampFieldMapper().fieldType().stored()); + assertTrue(documentMapper.timestampFieldMapper().hasDocValues()); + documentMapper.refreshSource(); + documentMapper = indexService.mapperService().parse("type", new CompressedString(documentMapper.mappingSource().string()), true); + assertThat(documentMapper.timestampFieldMapper().enabled(), equalTo(enabled)); + assertTrue(documentMapper.timestampFieldMapper().hasDocValues()); + assertTrue(documentMapper.timestampFieldMapper().fieldType().stored()); + } + + @Test + public void testSizeParsing() throws IOException { + IndexService indexService = createIndex("test", ImmutableSettings.settingsBuilder().build()); + XContentBuilder indexMapping = XContentFactory.jsonBuilder(); + boolean enabled = randomBoolean(); + indexMapping.startObject() + .startObject("type") + .startObject("_size") + .field("enabled", enabled) + .field("store", true) + .endObject() + .endObject() + .endObject(); + DocumentMapper documentMapper = indexService.mapperService().parse("type", new CompressedString(indexMapping.string()), true); + assertThat(documentMapper.sizeFieldMapper().enabled(), equalTo(enabled)); + assertTrue(documentMapper.sizeFieldMapper().fieldType().stored()); + documentMapper.refreshSource(); + documentMapper = indexService.mapperService().parse("type", new CompressedString(documentMapper.mappingSource().string()), true); + assertThat(documentMapper.sizeFieldMapper().enabled(), equalTo(enabled)); + } + + @Test + public void testSizeTimestampIndexParsing() throws IOException { + IndexService indexService = createIndex("test", ImmutableSettings.settingsBuilder().build()); + String mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/update/default_mapping_with_disabled_root_types.json"); + DocumentMapper documentMapper = indexService.mapperService().parse("type", new CompressedString(mapping), true); + assertThat(documentMapper.mappingSource().string(), equalTo(mapping)); + documentMapper.refreshSource(); + documentMapper = indexService.mapperService().parse("type", new CompressedString(documentMapper.mappingSource().string()), true); + assertThat(documentMapper.mappingSource().string(), equalTo(mapping)); + } + + @Test + public void testDefaultApplied() throws IOException { + createIndex("test1", ImmutableSettings.settingsBuilder().build()); + createIndex("test2", ImmutableSettings.settingsBuilder().build()); + XContentBuilder defaultMapping = XContentFactory.jsonBuilder().startObject() + .startObject(MapperService.DEFAULT_MAPPING).startObject("_size").field("enabled", true).endObject().endObject() + .endObject(); + client().admin().indices().preparePutMapping().setType(MapperService.DEFAULT_MAPPING).setSource(defaultMapping).get(); + XContentBuilder typeMapping = XContentFactory.jsonBuilder().startObject() + .startObject("type").startObject("_all").field("enabled", false).endObject().endObject() + .endObject(); + client().admin().indices().preparePutMapping("test1").setType("type").setSource(typeMapping).get(); + client().admin().indices().preparePutMapping("test1", "test2").setType("type").setSource(typeMapping).get(); + + GetMappingsResponse response = client().admin().indices().prepareGetMappings("test2").get(); + assertNotNull(response.getMappings().get("test2").get("type").getSourceAsMap().get("_all")); + assertFalse((Boolean) ((LinkedHashMap) response.getMappings().get("test2").get("type").getSourceAsMap().get("_all")).get("enabled")); + assertNotNull(response.getMappings().get("test2").get("type").getSourceAsMap().get("_size")); + assertTrue((Boolean)((LinkedHashMap)response.getMappings().get("test2").get("type").getSourceAsMap().get("_size")).get("enabled")); + } +} diff --git a/src/test/java/org/elasticsearch/index/mapper/update/default_mapping_with_disabled_root_types.json b/src/test/java/org/elasticsearch/index/mapper/update/default_mapping_with_disabled_root_types.json new file mode 100644 index 0000000000000..d8a6ea95c4440 --- /dev/null +++ b/src/test/java/org/elasticsearch/index/mapper/update/default_mapping_with_disabled_root_types.json @@ -0,0 +1 @@ +{"type":{"_timestamp":{"enabled":false,"fielddata":{"format":"doc_values"}},"_index":{"store":true,"enabled":false,"fielddata":{"format":"fst"}},"_size":{"enabled":false},"properties":{}}} \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/timestamp/SimpleTimestampTests.java b/src/test/java/org/elasticsearch/timestamp/SimpleTimestampTests.java index 6b4f2ce7898d1..4f646fa5b0a03 100644 --- a/src/test/java/org/elasticsearch/timestamp/SimpleTimestampTests.java +++ b/src/test/java/org/elasticsearch/timestamp/SimpleTimestampTests.java @@ -99,7 +99,7 @@ public void testThatUpdatingMappingShouldNotRemoveTimestampConfiguration() throw assertAcked(client().admin().indices().prepareCreate(index).addMapping(type, builder)); // check mapping again - assertTimestampMappingEnabled(index, type); + assertTimestampMappingEnabled(index, type, true); // update some field in the mapping XContentBuilder updateMappingBuilder = jsonBuilder().startObject().startObject("properties").startObject("otherField").field("type", "string").endObject().endObject(); @@ -107,14 +107,34 @@ public void testThatUpdatingMappingShouldNotRemoveTimestampConfiguration() throw assertAcked(putMappingResponse); // make sure timestamp field is still in mapping - assertTimestampMappingEnabled(index, type); + assertTimestampMappingEnabled(index, type, true); } - private void assertTimestampMappingEnabled(String index, String type) { + @Test + public void testThatTimestampCanBeSwitchedOnAndOff() throws Exception { + String index = "foo"; + String type = "mytype"; + + XContentBuilder builder = jsonBuilder().startObject().startObject("_timestamp").field("enabled", true).field("store", true).endObject().endObject(); + assertAcked(client().admin().indices().prepareCreate(index).addMapping(type, builder)); + + // check mapping again + assertTimestampMappingEnabled(index, type, true); + + // update some field in the mapping + XContentBuilder updateMappingBuilder = jsonBuilder().startObject().startObject("_timestamp").field("enabled", false).endObject().endObject(); + PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping(index).setType(type).setSource(updateMappingBuilder).get(); + assertAcked(putMappingResponse); + + // make sure timestamp field is still in mapping + assertTimestampMappingEnabled(index, type, false); + } + + private void assertTimestampMappingEnabled(String index, String type, boolean enabled) { GetMappingsResponse getMappingsResponse = client().admin().indices().prepareGetMappings(index).addTypes(type).get(); MappingMetaData.Timestamp timestamp = getMappingsResponse.getMappings().get(index).get(type).timestamp(); assertThat(timestamp, is(notNullValue())); - String errMsg = String.format(Locale.ROOT, "Expected timestamp field mapping to be enabled for %s/%s", index, type); - assertThat(errMsg, timestamp.enabled(), is(true)); + String errMsg = String.format(Locale.ROOT, "Expected timestamp field mapping to be "+ (enabled ? "enabled" : "disabled") +" for %s/%s", index, type); + assertThat(errMsg, timestamp.enabled(), is(enabled)); } }