Add an `include_type_name` option. (#29453)
This adds an `include_type_name` option to the `indices.create`, `indices.get_mapping` and `indices.put_mapping` APIs, which defaults to `true`. When set to `false`, then mappings will be returned directly in the body of the `indices.get_mapping` API, without keying them by the type name, the `indices.create` will expect mappings directly under the `mappings` key, and the `indices.put_mapping` will use `_doc` as a type name and fail if a `type` is provided explicitly. Relates #15613
This commit is contained in:
parent
45e7e24736
commit
6a6c0ea5e6
|
@ -173,3 +173,28 @@ PUT test?wait_for_active_shards=2
|
|||
|
||||
A detailed explanation of `wait_for_active_shards` and its possible values can be found
|
||||
<<index-wait-for-active-shards,here>>.
|
||||
|
||||
[float]
|
||||
=== Skipping types
|
||||
|
||||
Types are scheduled to be fully removed in Elasticsearch 8.0 and will not appear
|
||||
in requests or responses anymore. You can opt in for this future behaviour by
|
||||
setting `include_type_name=false` and putting mappings directly under `mappings`
|
||||
in the index creation call.
|
||||
|
||||
Here is an example:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
PUT test?include_type_name=false
|
||||
{
|
||||
"mappings": {
|
||||
"properties": {
|
||||
"foo": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
|
|
|
@ -41,3 +41,48 @@ GET /_mapping
|
|||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
// TEST[setup:twitter]
|
||||
|
||||
[float]
|
||||
=== Skipping types
|
||||
|
||||
Types are scheduled to be fully removed in Elasticsearch 8.0 and will not appear
|
||||
in requests or responses anymore. You can opt in for this future behaviour by
|
||||
setting `include_type_name=false` in the request, which will return mappings
|
||||
directly under `mappings` without keying by the type name.
|
||||
|
||||
Here is an example:
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
PUT test?include_type_name=false
|
||||
{
|
||||
"mappings": {
|
||||
"properties": {
|
||||
"foo": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GET test/_mappings?include_type_name=false
|
||||
--------------------------------------------------
|
||||
// CONSOLE
|
||||
|
||||
which returns
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
{
|
||||
"test": {
|
||||
"mappings": {
|
||||
"properties": {
|
||||
"foo": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
--------------------------------------------------
|
||||
// TESTRESPONSE
|
||||
|
|
|
@ -109,3 +109,54 @@ PUT my_index/_mapping/_doc
|
|||
|
||||
Each <<mapping-params,mapping parameter>> specifies whether or not its setting
|
||||
can be updated on an existing field.
|
||||
|
||||
[float]
|
||||
=== Skipping types
|
||||
|
||||
Types are scheduled to be fully removed in Elasticsearch 8.0 and will not appear
|
||||
in requests or responses anymore. You can opt in for this future behaviour by
|
||||
setting `include_type_name=false`.
|
||||
|
||||
NOTE: This should only be done on indices that have been created with
|
||||
`include_type_name=false` or that used `_doc` as a type name.
|
||||
|
||||
The Console script from the above section is equivalent to the below invocation:
|
||||
|
||||
[source,js]
|
||||
-----------------------------------
|
||||
PUT my_index?include_type_name=false <1>
|
||||
{
|
||||
"mappings": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"properties": {
|
||||
"first": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_id": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PUT my_index/_mapping?include_type_name=false
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
"properties": {
|
||||
"last": { <2>
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_id": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 100 <3>
|
||||
}
|
||||
}
|
||||
}
|
||||
-----------------------------------
|
||||
// CONSOLE
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
}
|
||||
},
|
||||
"params": {
|
||||
"include_type_name": {
|
||||
"type" : "string",
|
||||
"description" : "Whether a type should be expected in the body of the mappings."
|
||||
},
|
||||
"wait_for_active_shards": {
|
||||
"type" : "string",
|
||||
"description" : "Set the number of active shards to wait for before the operation returns."
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
}
|
||||
},
|
||||
"params": {
|
||||
"include_type_name": {
|
||||
"type" : "string",
|
||||
"description" : "Whether to add the type name to the response"
|
||||
},
|
||||
"ignore_unavailable": {
|
||||
"type" : "boolean",
|
||||
"description" : "Whether specified concrete indices should be ignored when unavailable (missing or closed)"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"methods": ["PUT", "POST"],
|
||||
"url": {
|
||||
"path": "/{index}/{type}/_mapping",
|
||||
"paths": ["/{index}/{type}/_mapping", "/{index}/_mapping/{type}", "/_mapping/{type}", "/{index}/{type}/_mappings", "/{index}/_mappings/{type}", "/_mappings/{type}"],
|
||||
"paths": ["/{index}/{type}/_mapping", "/{index}/_mapping/{type}", "/_mapping/{type}", "/{index}/{type}/_mappings", "/{index}/_mappings/{type}", "/_mappings/{type}", "{index}/_mappings", "{index}/_mapping"],
|
||||
"parts": {
|
||||
"index": {
|
||||
"type" : "list",
|
||||
|
@ -12,11 +12,14 @@
|
|||
},
|
||||
"type": {
|
||||
"type" : "string",
|
||||
"required" : true,
|
||||
"description" : "The name of the document type"
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"include_type_name": {
|
||||
"type" : "string",
|
||||
"description" : "Whether a type should be expected in the body of the mappings."
|
||||
},
|
||||
"timeout": {
|
||||
"type" : "time",
|
||||
"description" : "Explicit operation timeout"
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
"Create indices and manage mappings without types":
|
||||
|
||||
- skip:
|
||||
version: " - 6.99.99"
|
||||
reason: include_type_name was introduced in 7.0.0
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: index
|
||||
include_type_name: false
|
||||
body:
|
||||
mappings:
|
||||
properties:
|
||||
foo:
|
||||
type: keyword
|
||||
|
||||
- do:
|
||||
indices.get_mapping:
|
||||
index: index
|
||||
include_type_name: false
|
||||
|
||||
- match: { index.mappings.properties.foo.type: "keyword" }
|
||||
|
||||
- do:
|
||||
indices.put_mapping:
|
||||
index: index
|
||||
include_type_name: false
|
||||
body:
|
||||
properties:
|
||||
bar:
|
||||
type: float
|
||||
|
||||
- do:
|
||||
indices.get_mapping:
|
||||
index: index
|
||||
include_type_name: false
|
||||
|
||||
- match: { index.mappings.properties.foo.type: "keyword" }
|
||||
- match: { index.mappings.properties.bar.type: "float" }
|
||||
|
||||
---
|
||||
"PUT mapping with a type and include_type_name: false":
|
||||
|
||||
- skip:
|
||||
version: " - 6.99.99"
|
||||
reason: include_type_name was introduced in 7.0.0
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: index
|
||||
|
||||
- do:
|
||||
catch: /illegal_argument_exception/
|
||||
indices.put_mapping:
|
||||
index: index
|
||||
type: _doc
|
||||
include_type_name: false
|
||||
body:
|
||||
properties:
|
||||
bar:
|
||||
type: float
|
||||
|
||||
---
|
||||
"Empty index with the include_type_name=false option":
|
||||
|
||||
- skip:
|
||||
version: " - 6.99.99"
|
||||
reason: include_type_name was introduced in 7.0.0
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: index
|
||||
include_type_name: false
|
||||
|
||||
- do:
|
||||
indices.get_mapping:
|
||||
index: index
|
||||
include_type_name: false
|
||||
|
||||
- match: { index.mappings: {} }
|
|
@ -23,12 +23,18 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
|||
import org.elasticsearch.action.support.ActiveShardCount;
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.action.RestToXContentListener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RestCreateIndexAction extends BaseRestHandler {
|
||||
public RestCreateIndexAction(Settings settings, RestController controller) {
|
||||
|
@ -43,9 +49,16 @@ public class RestCreateIndexAction extends BaseRestHandler {
|
|||
|
||||
@Override
|
||||
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
|
||||
final boolean includeTypeName = request.paramAsBoolean("include_type_name", true);
|
||||
CreateIndexRequest createIndexRequest = new CreateIndexRequest(request.param("index"));
|
||||
if (request.hasContent()) {
|
||||
createIndexRequest.source(request.content(), request.getXContentType());
|
||||
Map<String, Object> sourceAsMap = XContentHelper.convertToMap(request.content(), false, request.getXContentType()).v2();
|
||||
if (includeTypeName == false && sourceAsMap.containsKey("mappings")) {
|
||||
Map<String, Object> newSourceAsMap = new HashMap<>(sourceAsMap);
|
||||
newSourceAsMap.put("mappings", Collections.singletonMap(MapperService.SINGLE_MAPPING_NAME, sourceAsMap.get("mappings")));
|
||||
sourceAsMap = newSourceAsMap;
|
||||
}
|
||||
createIndexRequest.source(sourceAsMap, LoggingDeprecationHandler.INSTANCE);
|
||||
}
|
||||
createIndexRequest.timeout(request.paramAsTime("timeout", createIndexRequest.timeout()));
|
||||
createIndexRequest.masterNodeTimeout(request.paramAsTime("master_timeout", createIndexRequest.masterNodeTimeout()));
|
||||
|
|
|
@ -77,6 +77,7 @@ public class RestGetMappingAction extends BaseRestHandler {
|
|||
|
||||
@Override
|
||||
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
|
||||
final boolean includeTypeName = request.paramAsBoolean("include_type_name", true);
|
||||
final String[] indices = Strings.splitStringByCommaToArray(request.param("index"));
|
||||
final String[] types = request.paramAsStringArrayOrEmptyIfAll("type");
|
||||
final GetMappingsRequest getMappingsRequest = new GetMappingsRequest();
|
||||
|
@ -141,13 +142,29 @@ public class RestGetMappingAction extends BaseRestHandler {
|
|||
for (final ObjectObjectCursor<String, ImmutableOpenMap<String, MappingMetaData>> indexEntry : mappingsByIndex) {
|
||||
builder.startObject(indexEntry.key);
|
||||
{
|
||||
builder.startObject("mappings");
|
||||
{
|
||||
if (includeTypeName == false) {
|
||||
MappingMetaData mappings = null;
|
||||
for (final ObjectObjectCursor<String, MappingMetaData> typeEntry : indexEntry.value) {
|
||||
builder.field(typeEntry.key, typeEntry.value.sourceAsMap());
|
||||
if (typeEntry.key.equals("_default_") == false) {
|
||||
assert mappings == null;
|
||||
mappings = typeEntry.value;
|
||||
}
|
||||
}
|
||||
if (mappings == null) {
|
||||
// no mappings yet
|
||||
builder.startObject("mappings").endObject();
|
||||
} else {
|
||||
builder.field("mappings", mappings.sourceAsMap());
|
||||
}
|
||||
} else {
|
||||
builder.startObject("mappings");
|
||||
{
|
||||
for (final ObjectObjectCursor<String, MappingMetaData> typeEntry : indexEntry.value) {
|
||||
builder.field(typeEntry.key, typeEntry.value.sourceAsMap());
|
||||
}
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.elasticsearch.action.support.IndicesOptions;
|
|||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
|
@ -67,8 +68,13 @@ public class RestPutMappingAction extends BaseRestHandler {
|
|||
|
||||
@Override
|
||||
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
|
||||
final boolean includeTypeName = request.paramAsBoolean("include_type_name", true);
|
||||
PutMappingRequest putMappingRequest = putMappingRequest(Strings.splitStringByCommaToArray(request.param("index")));
|
||||
putMappingRequest.type(request.param("type"));
|
||||
final String type = request.param("type");
|
||||
if (type != null && includeTypeName == false) {
|
||||
throw new IllegalArgumentException("Cannot set include_type_name=false and provide a type at the same time");
|
||||
}
|
||||
putMappingRequest.type(includeTypeName ? type : MapperService.SINGLE_MAPPING_NAME);
|
||||
putMappingRequest.source(request.requiredContent(), request.getXContentType());
|
||||
putMappingRequest.timeout(request.paramAsTime("timeout", putMappingRequest.timeout()));
|
||||
putMappingRequest.masterNodeTimeout(request.paramAsTime("master_timeout", putMappingRequest.masterNodeTimeout()));
|
||||
|
|
Loading…
Reference in New Issue