Merge pull request #15508 from jpountz/fix/MetaDataMappingService
MetaDataMappingService should call MapperService.merge with the original mapping update.
This commit is contained in:
commit
76abf43f7f
|
@ -236,8 +236,8 @@ public class MetaDataMappingService extends AbstractComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClusterState applyRequest(ClusterState currentState, PutMappingClusterStateUpdateRequest request) throws IOException {
|
private ClusterState applyRequest(ClusterState currentState, PutMappingClusterStateUpdateRequest request) throws IOException {
|
||||||
Map<String, DocumentMapper> newMappers = new HashMap<>();
|
String mappingType = request.type();
|
||||||
Map<String, DocumentMapper> existingMappers = new HashMap<>();
|
CompressedXContent mappingUpdateSource = new CompressedXContent(request.source());
|
||||||
for (String index : request.indices()) {
|
for (String index : request.indices()) {
|
||||||
IndexService indexService = indicesService.indexServiceSafe(index);
|
IndexService indexService = indicesService.indexServiceSafe(index);
|
||||||
// try and parse it (no need to add it here) so we can bail early in case of parsing exception
|
// try and parse it (no need to add it here) so we can bail early in case of parsing exception
|
||||||
|
@ -245,9 +245,9 @@ public class MetaDataMappingService extends AbstractComponent {
|
||||||
DocumentMapper existingMapper = indexService.mapperService().documentMapper(request.type());
|
DocumentMapper existingMapper = indexService.mapperService().documentMapper(request.type());
|
||||||
if (MapperService.DEFAULT_MAPPING.equals(request.type())) {
|
if (MapperService.DEFAULT_MAPPING.equals(request.type())) {
|
||||||
// _default_ types do not go through merging, but we do test the new settings. Also don't apply the old default
|
// _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 CompressedXContent(request.source()), false);
|
newMapper = indexService.mapperService().parse(request.type(), mappingUpdateSource, false);
|
||||||
} else {
|
} else {
|
||||||
newMapper = indexService.mapperService().parse(request.type(), new CompressedXContent(request.source()), existingMapper == null);
|
newMapper = indexService.mapperService().parse(request.type(), mappingUpdateSource, existingMapper == null);
|
||||||
if (existingMapper != null) {
|
if (existingMapper != null) {
|
||||||
// first, simulate
|
// first, simulate
|
||||||
// this will just throw exceptions in case of problems
|
// this will just throw exceptions in case of problems
|
||||||
|
@ -270,36 +270,31 @@ public class MetaDataMappingService extends AbstractComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newMappers.put(index, newMapper);
|
if (mappingType == null) {
|
||||||
if (existingMapper != null) {
|
mappingType = newMapper.type();
|
||||||
existingMappers.put(index, existingMapper);
|
} else if (mappingType.equals(newMapper.type()) == false) {
|
||||||
|
throw new InvalidTypeNameException("Type name provided does not match type name within mapping definition");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert mappingType != null;
|
||||||
|
|
||||||
String mappingType = request.type();
|
|
||||||
if (mappingType == null) {
|
|
||||||
mappingType = newMappers.values().iterator().next().type();
|
|
||||||
} else if (!mappingType.equals(newMappers.values().iterator().next().type())) {
|
|
||||||
throw new InvalidTypeNameException("Type name provided does not match type name within mapping definition");
|
|
||||||
}
|
|
||||||
if (!MapperService.DEFAULT_MAPPING.equals(mappingType) && !PercolatorService.TYPE_NAME.equals(mappingType) && mappingType.charAt(0) == '_') {
|
if (!MapperService.DEFAULT_MAPPING.equals(mappingType) && !PercolatorService.TYPE_NAME.equals(mappingType) && mappingType.charAt(0) == '_') {
|
||||||
throw new InvalidTypeNameException("Document mapping type name can't start with '_'");
|
throw new InvalidTypeNameException("Document mapping type name can't start with '_'");
|
||||||
}
|
}
|
||||||
final Map<String, MappingMetaData> mappings = new HashMap<>();
|
final Map<String, MappingMetaData> mappings = new HashMap<>();
|
||||||
for (Map.Entry<String, DocumentMapper> entry : newMappers.entrySet()) {
|
for (String index : request.indices()) {
|
||||||
String index = entry.getKey();
|
|
||||||
// do the actual merge here on the master, and update the mapping source
|
// do the actual merge here on the master, and update the mapping source
|
||||||
DocumentMapper newMapper = entry.getValue();
|
|
||||||
IndexService indexService = indicesService.indexService(index);
|
IndexService indexService = indicesService.indexService(index);
|
||||||
if (indexService == null) {
|
if (indexService == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompressedXContent existingSource = null;
|
CompressedXContent existingSource = null;
|
||||||
if (existingMappers.containsKey(entry.getKey())) {
|
DocumentMapper existingMapper = indexService.mapperService().documentMapper(mappingType);
|
||||||
existingSource = existingMappers.get(entry.getKey()).mappingSource();
|
if (existingMapper != null) {
|
||||||
|
existingSource = existingMapper.mappingSource();
|
||||||
}
|
}
|
||||||
DocumentMapper mergedMapper = indexService.mapperService().merge(newMapper.type(), newMapper.mappingSource(), false, request.updateAllTypes());
|
DocumentMapper mergedMapper = indexService.mapperService().merge(mappingType, mappingUpdateSource, true, request.updateAllTypes());
|
||||||
CompressedXContent updatedSource = mergedMapper.mappingSource();
|
CompressedXContent updatedSource = mergedMapper.mappingSource();
|
||||||
|
|
||||||
if (existingSource != null) {
|
if (existingSource != null) {
|
||||||
|
@ -318,9 +313,9 @@ public class MetaDataMappingService extends AbstractComponent {
|
||||||
} else {
|
} else {
|
||||||
mappings.put(index, new MappingMetaData(mergedMapper));
|
mappings.put(index, new MappingMetaData(mergedMapper));
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("[{}] create_mapping [{}] with source [{}]", index, newMapper.type(), updatedSource);
|
logger.debug("[{}] create_mapping [{}] with source [{}]", index, mappingType, updatedSource);
|
||||||
} else if (logger.isInfoEnabled()) {
|
} else if (logger.isInfoEnabled()) {
|
||||||
logger.info("[{}] create_mapping [{}]", index, newMapper.type());
|
logger.info("[{}] create_mapping [{}]", index, mappingType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,6 +198,7 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
|
||||||
public DocumentMapper merge(String type, CompressedXContent mappingSource, boolean applyDefault, boolean updateAllTypes) {
|
public DocumentMapper merge(String type, CompressedXContent mappingSource, boolean applyDefault, boolean updateAllTypes) {
|
||||||
if (DEFAULT_MAPPING.equals(type)) {
|
if (DEFAULT_MAPPING.equals(type)) {
|
||||||
// verify we can parse it
|
// verify we can parse it
|
||||||
|
// NOTE: never apply the default here
|
||||||
DocumentMapper mapper = documentParser.parseCompressed(type, mappingSource);
|
DocumentMapper mapper = documentParser.parseCompressed(type, mappingSource);
|
||||||
// still add it as a document mapper so we have it registered and, for example, persisted back into
|
// still add it as a document mapper so we have it registered and, for example, persisted back into
|
||||||
// the cluster meta data if needed, or checked for existence
|
// the cluster meta data if needed, or checked for existence
|
||||||
|
@ -211,68 +212,70 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
|
||||||
}
|
}
|
||||||
return mapper;
|
return mapper;
|
||||||
} else {
|
} else {
|
||||||
return merge(parse(type, mappingSource, applyDefault), updateAllTypes);
|
try (ReleasableLock lock = mappingWriteLock.acquire()) {
|
||||||
|
// only apply the default mapping if we don't have the type yet
|
||||||
|
applyDefault &= mappers.containsKey(type) == false;
|
||||||
|
return merge(parse(type, mappingSource, applyDefault), updateAllTypes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// never expose this to the outside world, we need to reparse the doc mapper so we get fresh
|
// 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
|
// instances of field mappers to properly remove existing doc mapper
|
||||||
private DocumentMapper merge(DocumentMapper mapper, boolean updateAllTypes) {
|
private DocumentMapper merge(DocumentMapper mapper, boolean updateAllTypes) {
|
||||||
try (ReleasableLock lock = mappingWriteLock.acquire()) {
|
if (mapper.type().length() == 0) {
|
||||||
if (mapper.type().length() == 0) {
|
throw new InvalidTypeNameException("mapping type name is empty");
|
||||||
throw new InvalidTypeNameException("mapping type name is empty");
|
}
|
||||||
}
|
if (indexSettings.getIndexVersionCreated().onOrAfter(Version.V_2_0_0_beta1) && mapper.type().length() > 255) {
|
||||||
if (indexSettings.getIndexVersionCreated().onOrAfter(Version.V_2_0_0_beta1) && mapper.type().length() > 255) {
|
throw new InvalidTypeNameException("mapping type name [" + mapper.type() + "] is too long; limit is length 255 but was [" + mapper.type().length() + "]");
|
||||||
throw new InvalidTypeNameException("mapping type name [" + mapper.type() + "] is too long; limit is length 255 but was [" + mapper.type().length() + "]");
|
}
|
||||||
}
|
if (mapper.type().charAt(0) == '_') {
|
||||||
if (mapper.type().charAt(0) == '_') {
|
throw new InvalidTypeNameException("mapping type name [" + mapper.type() + "] can't start with '_'");
|
||||||
throw new InvalidTypeNameException("mapping type name [" + mapper.type() + "] can't start with '_'");
|
}
|
||||||
}
|
if (mapper.type().contains("#")) {
|
||||||
if (mapper.type().contains("#")) {
|
throw new InvalidTypeNameException("mapping type name [" + mapper.type() + "] should not include '#' in it");
|
||||||
throw new InvalidTypeNameException("mapping type name [" + mapper.type() + "] should not include '#' in it");
|
}
|
||||||
}
|
if (mapper.type().contains(",")) {
|
||||||
if (mapper.type().contains(",")) {
|
throw new InvalidTypeNameException("mapping type name [" + mapper.type() + "] should not include ',' in it");
|
||||||
throw new InvalidTypeNameException("mapping type name [" + mapper.type() + "] should not include ',' in it");
|
}
|
||||||
}
|
if (mapper.type().equals(mapper.parentFieldMapper().type())) {
|
||||||
if (mapper.type().equals(mapper.parentFieldMapper().type())) {
|
throw new IllegalArgumentException("The [_parent.type] option can't point to the same type");
|
||||||
throw new IllegalArgumentException("The [_parent.type] option can't point to the same type");
|
}
|
||||||
}
|
if (typeNameStartsWithIllegalDot(mapper)) {
|
||||||
if (typeNameStartsWithIllegalDot(mapper)) {
|
if (indexSettings.getIndexVersionCreated().onOrAfter(Version.V_2_0_0_beta1)) {
|
||||||
if (indexSettings.getIndexVersionCreated().onOrAfter(Version.V_2_0_0_beta1)) {
|
throw new IllegalArgumentException("mapping type name [" + mapper.type() + "] must not start with a '.'");
|
||||||
throw new IllegalArgumentException("mapping type name [" + mapper.type() + "] must not start with a '.'");
|
|
||||||
} else {
|
|
||||||
logger.warn("Type [{}] starts with a '.', it is recommended not to start a type name with a '.'", mapper.type());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// we can add new field/object mappers while the old ones are there
|
|
||||||
// since we get new instances of those, and when we remove, we remove
|
|
||||||
// by instance equality
|
|
||||||
DocumentMapper oldMapper = mappers.get(mapper.type());
|
|
||||||
|
|
||||||
if (oldMapper != null) {
|
|
||||||
oldMapper.merge(mapper.mapping(), false, updateAllTypes);
|
|
||||||
return oldMapper;
|
|
||||||
} else {
|
} else {
|
||||||
Tuple<Collection<ObjectMapper>, Collection<FieldMapper>> newMappers = checkMappersCompatibility(
|
logger.warn("Type [{}] starts with a '.', it is recommended not to start a type name with a '.'", mapper.type());
|
||||||
mapper.type(), mapper.mapping(), updateAllTypes);
|
|
||||||
Collection<ObjectMapper> newObjectMappers = newMappers.v1();
|
|
||||||
Collection<FieldMapper> newFieldMappers = newMappers.v2();
|
|
||||||
addMappers(mapper.type(), newObjectMappers, newFieldMappers);
|
|
||||||
|
|
||||||
for (DocumentTypeListener typeListener : typeListeners) {
|
|
||||||
typeListener.beforeCreate(mapper);
|
|
||||||
}
|
|
||||||
mappers = newMapBuilder(mappers).put(mapper.type(), mapper).map();
|
|
||||||
if (mapper.parentFieldMapper().active()) {
|
|
||||||
Set<String> newParentTypes = new HashSet<>(parentTypes.size() + 1);
|
|
||||||
newParentTypes.addAll(parentTypes);
|
|
||||||
newParentTypes.add(mapper.parentFieldMapper().type());
|
|
||||||
parentTypes = unmodifiableSet(newParentTypes);
|
|
||||||
}
|
|
||||||
assert assertSerialization(mapper);
|
|
||||||
return mapper;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// we can add new field/object mappers while the old ones are there
|
||||||
|
// since we get new instances of those, and when we remove, we remove
|
||||||
|
// by instance equality
|
||||||
|
DocumentMapper oldMapper = mappers.get(mapper.type());
|
||||||
|
|
||||||
|
if (oldMapper != null) {
|
||||||
|
oldMapper.merge(mapper.mapping(), false, updateAllTypes);
|
||||||
|
return oldMapper;
|
||||||
|
} else {
|
||||||
|
Tuple<Collection<ObjectMapper>, Collection<FieldMapper>> newMappers = checkMappersCompatibility(
|
||||||
|
mapper.type(), mapper.mapping(), updateAllTypes);
|
||||||
|
Collection<ObjectMapper> newObjectMappers = newMappers.v1();
|
||||||
|
Collection<FieldMapper> newFieldMappers = newMappers.v2();
|
||||||
|
addMappers(mapper.type(), newObjectMappers, newFieldMappers);
|
||||||
|
|
||||||
|
for (DocumentTypeListener typeListener : typeListeners) {
|
||||||
|
typeListener.beforeCreate(mapper);
|
||||||
|
}
|
||||||
|
mappers = newMapBuilder(mappers).put(mapper.type(), mapper).map();
|
||||||
|
if (mapper.parentFieldMapper().active()) {
|
||||||
|
Set<String> newParentTypes = new HashSet<>(parentTypes.size() + 1);
|
||||||
|
newParentTypes.addAll(parentTypes);
|
||||||
|
newParentTypes.add(mapper.parentFieldMapper().type());
|
||||||
|
parentTypes = unmodifiableSet(newParentTypes);
|
||||||
|
}
|
||||||
|
assert assertSerialization(mapper);
|
||||||
|
return mapper;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean typeNameStartsWithIllegalDot(DocumentMapper mapper) {
|
private boolean typeNameStartsWithIllegalDot(DocumentMapper mapper) {
|
||||||
|
|
Loading…
Reference in New Issue