Make sure to use the resolved type in DocumentMapperService#extractMappings. (#37451)
* Pull out a shared method MapperService#resolveDocumentType. * Make sure to resolve the type when extracting the mappings. Addresses #36811.
This commit is contained in:
parent
9554b2fecb
commit
1a1dbf705f
|
@ -60,3 +60,41 @@
|
|||
- match: { _id: $id}
|
||||
- match: { _version: 1}
|
||||
- match: { _source: { foo: bar }}
|
||||
|
||||
---
|
||||
"Index call that introduces new field mappings":
|
||||
|
||||
- skip:
|
||||
version: " - 6.99.99"
|
||||
reason: Typeless APIs were introduced in 7.0.0
|
||||
|
||||
- do:
|
||||
indices.create: # not using include_type_name: false on purpose
|
||||
index: index
|
||||
body:
|
||||
mappings:
|
||||
not_doc:
|
||||
properties:
|
||||
foo:
|
||||
type: "keyword"
|
||||
- do:
|
||||
index:
|
||||
index: index
|
||||
id: 2
|
||||
body: { new_field: value }
|
||||
|
||||
- match: { _index: "index" }
|
||||
- match: { _type: "_doc" }
|
||||
- match: { _id: "2" }
|
||||
- match: { _version: 1 }
|
||||
|
||||
- do:
|
||||
get: # using typeful API on purpose
|
||||
index: index
|
||||
type: not_doc
|
||||
id: 2
|
||||
|
||||
- match: { _index: "index" }
|
||||
- match: { _type: "not_doc" }
|
||||
- match: { _id: "2" }
|
||||
- match: { _version: 1}
|
||||
|
|
|
@ -37,3 +37,48 @@
|
|||
id: 1
|
||||
|
||||
- match: { _source.foo: baz }
|
||||
|
||||
---
|
||||
"Update call that introduces new field mappings":
|
||||
|
||||
- skip:
|
||||
version: " - 6.99.99"
|
||||
reason: Typeless APIs were introduced in 7.0.0
|
||||
|
||||
- do:
|
||||
indices.create: # not using include_type_name: false on purpose
|
||||
index: index
|
||||
body:
|
||||
mappings:
|
||||
not_doc:
|
||||
properties:
|
||||
foo:
|
||||
type: "keyword"
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: index
|
||||
type: not_doc
|
||||
id: 1
|
||||
body: { foo: bar }
|
||||
|
||||
- do:
|
||||
update:
|
||||
index: index
|
||||
id: 1
|
||||
body:
|
||||
doc:
|
||||
foo: baz
|
||||
new_field: value
|
||||
- do:
|
||||
get: # using typeful API on purpose
|
||||
index: index
|
||||
type: not_doc
|
||||
id: 1
|
||||
|
||||
- match: { _index: "index" }
|
||||
- match: { _type: "not_doc" }
|
||||
- match: { _id: "1" }
|
||||
- match: { _version: 2}
|
||||
- match: { _source.foo: baz }
|
||||
- match: { _source.new_field: value }
|
||||
|
|
|
@ -276,8 +276,9 @@ public class MetaDataMappingService {
|
|||
}
|
||||
if (mappingType == null) {
|
||||
mappingType = newMapper.type();
|
||||
} else if (mappingType.equals(newMapper.type()) == false) {
|
||||
throw new InvalidTypeNameException("Type name provided does not match type name within mapping definition");
|
||||
} else if (mappingType.equals(newMapper.type()) == false
|
||||
&& mapperService.resolveDocumentType(mappingType).equals(newMapper.type()) == false) {
|
||||
throw new InvalidTypeNameException("Type name provided does not match type name within mapping definition.");
|
||||
}
|
||||
}
|
||||
assert mappingType != null;
|
||||
|
@ -295,16 +296,12 @@ public class MetaDataMappingService {
|
|||
// we use the exact same indexService and metadata we used to validate above here to actually apply the update
|
||||
final Index index = indexMetaData.getIndex();
|
||||
final MapperService mapperService = indexMapperServices.get(index);
|
||||
String typeForUpdate = mappingType; // the type to use to apply the mapping update
|
||||
if (MapperService.SINGLE_MAPPING_NAME.equals(typeForUpdate)) {
|
||||
// If the user gave _doc as a special type value or if (s)he is using the new typeless APIs,
|
||||
// then we apply the mapping update to the existing type. This allows to move to typeless
|
||||
// APIs with indices whose type name is different from `_doc`.
|
||||
DocumentMapper mapper = mapperService.documentMapper();
|
||||
if (mapper != null) {
|
||||
typeForUpdate = mapper.type();
|
||||
}
|
||||
}
|
||||
|
||||
// If the user gave _doc as a special type value or if they are using the new typeless APIs,
|
||||
// then we apply the mapping update to the existing type. This allows to move to typeless
|
||||
// APIs with indices whose type name is different from `_doc`.
|
||||
String typeForUpdate = mapperService.resolveDocumentType(mappingType); // the type to use to apply the mapping update
|
||||
|
||||
CompressedXContent existingSource = null;
|
||||
DocumentMapper existingMapper = mapperService.documentMapper(typeForUpdate);
|
||||
if (existingMapper != null) {
|
||||
|
|
|
@ -197,7 +197,7 @@ public class DocumentMapperParser {
|
|||
|
||||
String rootName = root.keySet().iterator().next();
|
||||
Tuple<String, Map<String, Object>> mapping;
|
||||
if (type == null || type.equals(rootName)) {
|
||||
if (type == null || type.equals(rootName) || mapperService.resolveDocumentType(type).equals(rootName)) {
|
||||
mapping = new Tuple<>(rootName, (Map<String, Object>) root.get(rootName));
|
||||
} else {
|
||||
mapping = new Tuple<>(type, root);
|
||||
|
|
|
@ -665,6 +665,23 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a type from a mapping-related request into the type that should be used when
|
||||
* merging and updating mappings.
|
||||
*
|
||||
* If the special `_doc` type is provided, then we replace it with the actual type that is
|
||||
* being used in the mappings. This allows typeless APIs such as 'index' or 'put mappings'
|
||||
* to work against indices with a custom type name.
|
||||
*/
|
||||
public String resolveDocumentType(String type) {
|
||||
if (MapperService.SINGLE_MAPPING_NAME.equals(type)) {
|
||||
if (mapper != null) {
|
||||
return mapper.type();
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the document mapper created, including a mapping update if the
|
||||
* type has been dynamically created.
|
||||
|
|
|
@ -721,7 +721,7 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
|
|||
ensureWriteAllowed(origin);
|
||||
Engine.Index operation;
|
||||
try {
|
||||
final String resolvedType = resolveType(sourceToParse.type());
|
||||
final String resolvedType = mapperService.resolveDocumentType(sourceToParse.type());
|
||||
final SourceToParse sourceWithResolvedType;
|
||||
if (resolvedType.equals(sourceToParse.type())) {
|
||||
sourceWithResolvedType = sourceToParse;
|
||||
|
@ -844,11 +844,12 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
|
|||
} catch (MapperParsingException | IllegalArgumentException | TypeMissingException e) {
|
||||
return new Engine.DeleteResult(e, version, operationPrimaryTerm, seqNo, false);
|
||||
}
|
||||
if (resolveType(type).equals(mapperService.documentMapper().type()) == false) {
|
||||
if (mapperService.resolveDocumentType(type).equals(mapperService.documentMapper().type()) == false) {
|
||||
// We should never get there due to the fact that we generate mapping updates on deletes,
|
||||
// but we still prefer to have a hard exception here as we would otherwise delete a
|
||||
// document in the wrong type.
|
||||
throw new IllegalStateException("Deleting document from type [" + resolveType(type) + "] while current type is [" +
|
||||
throw new IllegalStateException("Deleting document from type [" +
|
||||
mapperService.resolveDocumentType(type) + "] while current type is [" +
|
||||
mapperService.documentMapper().type() + "]");
|
||||
}
|
||||
final Term uid = new Term(IdFieldMapper.NAME, Uid.encodeId(id));
|
||||
|
@ -861,8 +862,8 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
|
|||
VersionType versionType, Engine.Operation.Origin origin,
|
||||
long ifSeqNo, long ifPrimaryTerm) {
|
||||
long startTime = System.nanoTime();
|
||||
return new Engine.Delete(resolveType(type), id, uid, seqNo, primaryTerm, version, versionType, origin, startTime,
|
||||
ifSeqNo, ifPrimaryTerm);
|
||||
return new Engine.Delete(mapperService.resolveDocumentType(type), id, uid, seqNo, primaryTerm, version, versionType,
|
||||
origin, startTime, ifSeqNo, ifPrimaryTerm);
|
||||
}
|
||||
|
||||
private Engine.DeleteResult delete(Engine engine, Engine.Delete delete) throws IOException {
|
||||
|
@ -885,7 +886,7 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
|
|||
public Engine.GetResult get(Engine.Get get) {
|
||||
readAllowed();
|
||||
DocumentMapper mapper = mapperService.documentMapper();
|
||||
if (mapper == null || mapper.type().equals(resolveType(get.type())) == false) {
|
||||
if (mapper == null || mapper.type().equals(mapperService.resolveDocumentType(get.type())) == false) {
|
||||
return GetResult.NOT_EXISTS;
|
||||
}
|
||||
return getEngine().get(get, this::acquireSearcher);
|
||||
|
@ -2319,23 +2320,10 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If an index/update/get/delete operation is using the special `_doc` type, then we replace
|
||||
* it with the actual type that is being used in the mappings so that users may use typeless
|
||||
* APIs with indices that have types.
|
||||
*/
|
||||
private String resolveType(String type) {
|
||||
if (MapperService.SINGLE_MAPPING_NAME.equals(type)) {
|
||||
DocumentMapper docMapper = mapperService.documentMapper();
|
||||
if (docMapper != null) {
|
||||
return docMapper.type();
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private DocumentMapperForType docMapper(String type) {
|
||||
return mapperService.documentMapperWithAutoCreate(resolveType(type));
|
||||
return mapperService.documentMapperWithAutoCreate(
|
||||
mapperService.resolveDocumentType(type));
|
||||
}
|
||||
|
||||
private EngineConfig newEngineConfig() {
|
||||
|
|
Loading…
Reference in New Issue