when changing the mapping of the _default_ mapping, do not apply the old _default_ mapping to the new one and also do not validate the new version with a merge but parse is as a new type.

Closes #3474, Closes #3476
This commit is contained in:
Boaz Leskes 2013-08-09 19:54:06 +02:00
parent f64065c9d2
commit 5f4dc5433e
2 changed files with 79 additions and 9 deletions

View File

@ -387,9 +387,13 @@ public class MetaDataMappingService extends AbstractComponent {
IndexService indexService = indicesService.indexService(index);
if (indexService != null) {
// try and parse it (no need to add it here) so we can bail early in case of parsing exception
DocumentMapper newMapper = indexService.mapperService().parse(request.mappingType, request.mappingSource);
newMappers.put(index, newMapper);
DocumentMapper newMapper;
DocumentMapper existingMapper = indexService.mapperService().documentMapper(request.mappingType);
if (MapperService.DEFAULT_MAPPING.equals(request.mappingType)) {
// _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.mappingType, request.mappingSource, false);
} else {
newMapper = indexService.mapperService().parse(request.mappingType, request.mappingSource);
if (existingMapper != null) {
// first, simulate
DocumentMapper.MergeResult mergeResult = existingMapper.merge(newMapper, mergeFlags().simulate(true));
@ -397,8 +401,14 @@ public class MetaDataMappingService extends AbstractComponent {
if (!request.ignoreConflicts && mergeResult.hasConflicts()) {
throw new MergeMappingException(mergeResult.conflicts());
}
}
}
newMappers.put(index, newMapper);
if (existingMapper != null) {
existingMappers.put(index, existingMapper);
}
} else {
throw new IndexMissingException(new Index(index));
}

View File

@ -1,15 +1,22 @@
package org.elasticsearch.test.integration.indices.mapping;
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
import org.elasticsearch.action.count.CountResponse;
import org.elasticsearch.common.Priority;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.MergeMappingException;
import org.elasticsearch.test.integration.AbstractSharedClusterTest;
import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;
import java.util.Map;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertThrows;
import static org.hamcrest.Matchers.*;
public class UpdateMappingTests extends AbstractSharedClusterTest {
@ -100,4 +107,57 @@ public class UpdateMappingTests extends AbstractSharedClusterTest {
//no changes, we return
assertThat(putMappingResponse.isAcknowledged(), equalTo(true));
}
@SuppressWarnings("unchecked")
@Test
public void updateDefaultMappingSettings() throws Exception {
client().admin().indices().prepareCreate("test").addMapping(MapperService.DEFAULT_MAPPING,
JsonXContent.contentBuilder().startObject().startObject(MapperService.DEFAULT_MAPPING)
.field("date_detection", false)
.endObject().endObject()
).get();
GetMappingsResponse response = client().admin().indices().prepareGetMappings("test").addTypes(MapperService.DEFAULT_MAPPING).get();
Map<String, Object> defaultMapping = response.getMappings().get("test").get(MapperService.DEFAULT_MAPPING).sourceAsMap();
assertThat(defaultMapping, hasKey("date_detection"));
// now remove it
client().admin().indices().preparePutMapping("test").setType(MapperService.DEFAULT_MAPPING).setSource(
JsonXContent.contentBuilder().startObject().startObject(MapperService.DEFAULT_MAPPING)
.endObject().endObject()
).get();
response = client().admin().indices().prepareGetMappings("test").addTypes(MapperService.DEFAULT_MAPPING).get();
defaultMapping = response.getMappings().get("test").get(MapperService.DEFAULT_MAPPING).sourceAsMap();
assertThat(defaultMapping, not(hasKey("date_detection")));
// now test you can change stuff that are normally unchangable
client().admin().indices().preparePutMapping("test").setType(MapperService.DEFAULT_MAPPING).setSource(
JsonXContent.contentBuilder().startObject().startObject(MapperService.DEFAULT_MAPPING)
.startObject("properties").startObject("f").field("type", "string").field("index", "analyzed").endObject().endObject()
.endObject().endObject()
).get();
client().admin().indices().preparePutMapping("test").setType(MapperService.DEFAULT_MAPPING).setSource(
JsonXContent.contentBuilder().startObject().startObject(MapperService.DEFAULT_MAPPING)
.startObject("properties").startObject("f").field("type", "string").field("index", "not_analyzed").endObject().endObject()
.endObject().endObject()
).get();
response = client().admin().indices().prepareGetMappings("test").addTypes(MapperService.DEFAULT_MAPPING).get();
defaultMapping = response.getMappings().get("test").get(MapperService.DEFAULT_MAPPING).sourceAsMap();
Map<String, Object> fieldSettings = (Map<String, Object>) ((Map) defaultMapping.get("properties")).get("f");
assertThat(fieldSettings, hasEntry("index", (Object) "not_analyzed"));
// but we still validate the _default_ type
assertThrows(client().admin().indices().preparePutMapping("test").setType(MapperService.DEFAULT_MAPPING).setSource(
JsonXContent.contentBuilder().startObject().startObject(MapperService.DEFAULT_MAPPING)
.startObject("properties").startObject("f").field("type", "DOESNT_EXIST").endObject().endObject()
.endObject().endObject()
), MapperParsingException.class);
}
}