Skip to content

Commit c149bb8

Browse files
author
Christoph Büscher
authored
Support 'include_type_name' in RestGetIndicesAction (#37149)
This change adds support for the 'include_type_name' parameter for the indices.get API. This parameter, which defaults to `false` starting in 7.0, changes the response to not include the indices type names any longer. If the parameter is set in the request, we additionally emit a deprecation warning since using the parameter should be only temporarily necessary while adapting to the new response format and we will remove it with the next major version.
1 parent 84d520b commit c149bb8

File tree

11 files changed

+251
-42
lines changed

11 files changed

+251
-42
lines changed

client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
import org.elasticsearch.common.xcontent.json.JsonXContent;
9090
import org.elasticsearch.common.xcontent.support.XContentMapValues;
9191
import org.elasticsearch.index.IndexSettings;
92+
import org.elasticsearch.index.mapper.MapperService;
9293
import org.elasticsearch.index.query.QueryBuilder;
9394
import org.elasticsearch.index.query.QueryBuilders;
9495
import org.elasticsearch.rest.RestStatus;
@@ -209,7 +210,7 @@ public void testCreateIndex() throws IOException {
209210
mappingBuilder.startObject().startObject("properties").startObject("field");
210211
mappingBuilder.field("type", "text");
211212
mappingBuilder.endObject().endObject().endObject();
212-
createIndexRequest.mapping("type_name", mappingBuilder);
213+
createIndexRequest.mapping(MapperService.SINGLE_MAPPING_NAME, mappingBuilder);
213214

214215
CreateIndexResponse createIndexResponse =
215216
execute(createIndexRequest, highLevelClient().indices()::create, highLevelClient().indices()::createAsync);
@@ -226,7 +227,7 @@ public void testCreateIndex() throws IOException {
226227
Map<String, Object> term = (Map) filter.get("term");
227228
assertEquals(2016, term.get("year"));
228229

229-
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.type_name.properties.field.type", getIndexResponse));
230+
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.properties.field.type", getIndexResponse));
230231
}
231232
}
232233

@@ -340,7 +341,7 @@ public void testGetIndex() throws IOException {
340341
.put(SETTING_NUMBER_OF_SHARDS, 1)
341342
.put(SETTING_NUMBER_OF_REPLICAS, 0)
342343
.build();
343-
String mappings = "\"type-1\":{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}";
344+
String mappings = "\"_doc\":{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}";
344345
createIndex(indexName, basicSettings, mappings);
345346

346347
GetIndexRequest getIndexRequest = new GetIndexRequest()
@@ -353,8 +354,8 @@ public void testGetIndex() throws IOException {
353354
assertEquals("1", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_SHARDS));
354355
assertEquals("0", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_REPLICAS));
355356
assertNotNull(getIndexResponse.getMappings().get(indexName));
356-
assertNotNull(getIndexResponse.getMappings().get(indexName).get("type-1"));
357-
Object o = getIndexResponse.getMappings().get(indexName).get("type-1").getSourceAsMap().get("properties");
357+
assertNotNull(getIndexResponse.getMappings().get(indexName).get("_doc"));
358+
Object o = getIndexResponse.getMappings().get(indexName).get("_doc").getSourceAsMap().get("properties");
358359
assertThat(o, instanceOf(Map.class));
359360
//noinspection unchecked
360361
assertThat(((Map<String, Object>) o).get("field-1"), instanceOf(Map.class));
@@ -370,7 +371,7 @@ public void testGetIndexWithDefaults() throws IOException {
370371
.put(SETTING_NUMBER_OF_SHARDS, 1)
371372
.put(SETTING_NUMBER_OF_REPLICAS, 0)
372373
.build();
373-
String mappings = "\"type-1\":{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}";
374+
String mappings = "\"_doc\":{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}";
374375
createIndex(indexName, basicSettings, mappings);
375376

376377
GetIndexRequest getIndexRequest = new GetIndexRequest()
@@ -384,8 +385,8 @@ public void testGetIndexWithDefaults() throws IOException {
384385
assertEquals("1", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_SHARDS));
385386
assertEquals("0", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_REPLICAS));
386387
assertNotNull(getIndexResponse.getMappings().get(indexName));
387-
assertNotNull(getIndexResponse.getMappings().get(indexName).get("type-1"));
388-
Object o = getIndexResponse.getMappings().get(indexName).get("type-1").getSourceAsMap().get("properties");
388+
assertNotNull(getIndexResponse.getMappings().get(indexName).get("_doc"));
389+
Object o = getIndexResponse.getMappings().get(indexName).get("_doc").getSourceAsMap().get("properties");
389390
assertThat(o, instanceOf(Map.class));
390391
assertThat(((Map<String, Object>) o).get("field-1"), instanceOf(Map.class));
391392
Map<String, Object> fieldMapping = (Map<String, Object>) ((Map<String, Object>) o).get("field-1");
@@ -408,7 +409,7 @@ public void testPutMapping() throws IOException {
408409
createIndex(indexName, Settings.EMPTY);
409410

410411
PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
411-
putMappingRequest.type("type_name");
412+
putMappingRequest.type("_doc");
412413
XContentBuilder mappingBuilder = JsonXContent.contentBuilder();
413414
mappingBuilder.startObject().startObject("properties").startObject("field");
414415
mappingBuilder.field("type", "text");
@@ -420,7 +421,7 @@ public void testPutMapping() throws IOException {
420421
assertTrue(putMappingResponse.isAcknowledged());
421422

422423
Map<String, Object> getIndexResponse = getAsMap(indexName);
423-
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.type_name.properties.field.type", getIndexResponse));
424+
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.properties.field.type", getIndexResponse));
424425
}
425426

426427
public void testGetMapping() throws IOException {
@@ -440,7 +441,7 @@ public void testGetMapping() throws IOException {
440441
assertTrue(putMappingResponse.isAcknowledged());
441442

442443
Map<String, Object> getIndexResponse = getAsMap(indexName);
443-
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings._doc.properties.field.type", getIndexResponse));
444+
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.properties.field.type", getIndexResponse));
444445

445446
GetMappingsRequest request = new GetMappingsRequest()
446447
.indices(indexName)

client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,15 @@
7070
import org.elasticsearch.action.support.IndicesOptions;
7171
import org.elasticsearch.action.support.master.AcknowledgedResponse;
7272
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
73-
import org.elasticsearch.client.indices.FreezeIndexRequest;
7473
import org.elasticsearch.client.GetAliasesResponse;
7574
import org.elasticsearch.client.RequestOptions;
7675
import org.elasticsearch.client.RestHighLevelClient;
7776
import org.elasticsearch.client.SyncedFlushResponse;
77+
import org.elasticsearch.client.core.ShardsAcknowledgedResponse;
78+
import org.elasticsearch.client.indices.FreezeIndexRequest;
7879
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
7980
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
8081
import org.elasticsearch.client.indices.UnfreezeIndexRequest;
81-
import org.elasticsearch.client.core.ShardsAcknowledgedResponse;
8282
import org.elasticsearch.cluster.metadata.AliasMetaData;
8383
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
8484
import org.elasticsearch.cluster.metadata.MappingMetaData;
@@ -1249,7 +1249,7 @@ public void testGetIndex() throws Exception {
12491249
Settings settings = Settings.builder().put("number_of_shards", 3).build();
12501250
String mappings = "{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}";
12511251
CreateIndexResponse createIndexResponse = client.indices().create(
1252-
new CreateIndexRequest("index", settings).mapping("doc", mappings, XContentType.JSON),
1252+
new CreateIndexRequest("index", settings).mapping("_doc", mappings, XContentType.JSON),
12531253
RequestOptions.DEFAULT);
12541254
assertTrue(createIndexResponse.isAcknowledged());
12551255
}
@@ -1272,7 +1272,7 @@ public void testGetIndex() throws Exception {
12721272

12731273
// tag::get-index-response
12741274
ImmutableOpenMap<String, MappingMetaData> indexMappings = getIndexResponse.getMappings().get("index"); // <1>
1275-
Map<String, Object> indexTypeMappings = indexMappings.get("doc").getSourceAsMap(); // <2>
1275+
Map<String, Object> indexTypeMappings = indexMappings.get("_doc").getSourceAsMap(); // <2>
12761276
List<AliasMetaData> indexAliases = getIndexResponse.getAliases().get("index"); // <3>
12771277
String numberOfShardsString = getIndexResponse.getSetting("index", "index.number_of_shards"); // <4>
12781278
Settings indexSettings = getIndexResponse.getSettings().get("index"); // <5>

docs/reference/indices/get-index.asciidoc

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,63 @@ alias or wildcard expression is required.
1515

1616
The get index API can also be applied to more than one index, or on
1717
all indices by using `_all` or `*` as index.
18+
19+
[float]
20+
=== Skipping types
21+
22+
Types are scheduled to be fully removed in Elasticsearch 8.0 and will not appear
23+
in requests or responses anymore. You can opt in for this future behaviour by
24+
setting `include_type_name=false` in the request, which will return mappings
25+
directly under `mappings` without keying by the type name.
26+
27+
Here is an example:
28+
29+
[source,js]
30+
--------------------------------------------------
31+
PUT test?include_type_name=false
32+
{
33+
"mappings": {
34+
"properties": {
35+
"foo": {
36+
"type": "keyword"
37+
}
38+
}
39+
}
40+
}
41+
42+
GET test?include_type_name=false
43+
--------------------------------------------------
44+
// CONSOLE
45+
46+
which returns
47+
48+
[source,js]
49+
--------------------------------------------------
50+
{
51+
"test": {
52+
"aliases": {},
53+
"mappings": {
54+
"properties": {
55+
"foo": {
56+
"type": "keyword"
57+
}
58+
}
59+
},
60+
"settings": {
61+
"index": {
62+
"creation_date": "1547028674905",
63+
"number_of_shards": "1",
64+
"number_of_replicas": "1",
65+
"uuid": "u1YpkPqLSqGIn3kNAvY8cA",
66+
"version": {
67+
"created": ...
68+
},
69+
"provided_name": "test"
70+
}
71+
}
72+
}
73+
}
74+
--------------------------------------------------
75+
// TESTRESPONSE[s/1547028674905/$body.test.settings.index.creation_date/]
76+
// TESTRESPONSE[s/u1YpkPqLSqGIn3kNAvY8cA/$body.test.settings.index.uuid/]
77+
// TESTRESPONSE[s/"created": \.\.\./"created": $body.test.settings.index.version.created/]

rest-api-spec/src/main/resources/rest-api-spec/api/indices.get.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
}
1414
},
1515
"params":{
16+
"include_type_name": {
17+
"type" : "boolean",
18+
"description" : "Whether to add the type name to the response (default: false)"
19+
},
1620
"local":{
1721
"type":"boolean",
1822
"description":"Return local information, do not retrieve the state from master node (default: false)"

rest-api-spec/src/main/resources/rest-api-spec/test/indices.get/10_basic.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,35 @@ setup:
5252
- is_true: test_index.settings
5353
- is_true: test_index.mappings
5454

55+
---
56+
"Test include_type_name":
57+
- skip:
58+
version: " - 6.99.99"
59+
reason: the include_type_name parameter is not backported to pre 7.0 versions yet
60+
61+
- do:
62+
indices.get:
63+
include_type_name: true
64+
index: test_index
65+
66+
- is_true: test_index.mappings
67+
- is_true: test_index.mappings.type_1
68+
69+
- do:
70+
indices.get:
71+
include_type_name: false
72+
index: test_index
73+
74+
- is_true: test_index.mappings
75+
- is_false: test_index.mappings.type_1
76+
77+
- do:
78+
indices.get:
79+
index: test_index
80+
81+
- is_true: test_index.mappings
82+
- is_false: test_index.mappings.type_1
83+
5584
---
5685
"Get index infos should work for wildcards":
5786

server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexResponse.java

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.elasticsearch.action.admin.indices.get;
2121

2222
import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
23+
2324
import org.apache.lucene.util.CollectionUtil;
2425
import org.elasticsearch.Version;
2526
import org.elasticsearch.action.ActionResponse;
@@ -34,16 +35,19 @@
3435
import org.elasticsearch.common.xcontent.XContentBuilder;
3536
import org.elasticsearch.common.xcontent.XContentParser;
3637
import org.elasticsearch.common.xcontent.XContentParser.Token;
38+
import org.elasticsearch.index.mapper.MapperService;
3739

3840
import java.io.IOException;
3941
import java.util.ArrayList;
4042
import java.util.Arrays;
4143
import java.util.Collections;
4244
import java.util.Comparator;
4345
import java.util.List;
46+
import java.util.Map;
4447
import java.util.Objects;
4548

4649
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
50+
import static org.elasticsearch.rest.BaseRestHandler.INCLUDE_TYPE_NAME_PARAMETER;
4751

4852
/**
4953
* A response for a get index action.
@@ -249,15 +253,32 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
249253
}
250254
builder.endObject();
251255

252-
builder.startObject("mappings");
253256
ImmutableOpenMap<String, MappingMetaData> indexMappings = mappings.get(index);
254-
if (indexMappings != null) {
257+
boolean includeTypeName = params.paramAsBoolean(INCLUDE_TYPE_NAME_PARAMETER, false);
258+
if (includeTypeName) {
259+
builder.startObject("mappings");
260+
if (indexMappings != null) {
261+
for (final ObjectObjectCursor<String, MappingMetaData> typeEntry : indexMappings) {
262+
builder.field(typeEntry.key);
263+
builder.map(typeEntry.value.sourceAsMap());
264+
}
265+
}
266+
builder.endObject();
267+
} else {
268+
MappingMetaData mappings = null;
255269
for (final ObjectObjectCursor<String, MappingMetaData> typeEntry : indexMappings) {
256-
builder.field(typeEntry.key);
257-
builder.map(typeEntry.value.sourceAsMap());
270+
if (typeEntry.key.equals(MapperService.DEFAULT_MAPPING) == false) {
271+
assert mappings == null;
272+
mappings = typeEntry.value;
273+
}
274+
}
275+
if (mappings == null) {
276+
// no mappings yet
277+
builder.startObject("mappings").endObject();
278+
} else {
279+
builder.field("mappings", mappings.sourceAsMap());
258280
}
259281
}
260-
builder.endObject();
261282

262283
builder.startObject("settings");
263284
Settings indexSettings = settings.get(index);
@@ -292,16 +313,9 @@ private static List<AliasMetaData> parseAliases(XContentParser parser) throws IO
292313

293314
private static ImmutableOpenMap<String, MappingMetaData> parseMappings(XContentParser parser) throws IOException {
294315
ImmutableOpenMap.Builder<String, MappingMetaData> indexMappings = ImmutableOpenMap.builder();
295-
// We start at START_OBJECT since parseIndexEntry ensures that
296-
while (parser.nextToken() != Token.END_OBJECT) {
297-
ensureExpectedToken(Token.FIELD_NAME, parser.currentToken(), parser::getTokenLocation);
298-
parser.nextToken();
299-
if (parser.currentToken() == Token.START_OBJECT) {
300-
String mappingType = parser.currentName();
301-
indexMappings.put(mappingType, new MappingMetaData(mappingType, parser.map()));
302-
} else if (parser.currentToken() == Token.START_ARRAY) {
303-
parser.skipChildren();
304-
}
316+
Map<String, Object> map = parser.map();
317+
if (map.isEmpty() == false) {
318+
indexMappings.put(MapperService.SINGLE_MAPPING_NAME, new MappingMetaData(MapperService.SINGLE_MAPPING_NAME, map));
305319
}
306320
return indexMappings.build();
307321
}

server/src/main/java/org/elasticsearch/rest/BaseRestHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public abstract class BaseRestHandler extends AbstractComponent implements RestH
6262
* Parameter that controls whether certain REST apis should include type names in their requests or responses.
6363
* Note: Support for this parameter will be removed after the transition perido to typeless APIs.
6464
*/
65-
protected static final String INCLUDE_TYPE_NAME_PARAMETER = "include_type_name";
65+
public static final String INCLUDE_TYPE_NAME_PARAMETER = "include_type_name";
6666

6767
protected BaseRestHandler(Settings settings) {
6868
// TODO drop settings from ctor

server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,23 @@
2020
package org.elasticsearch.rest.action.admin.indices;
2121

2222

23+
import org.apache.logging.log4j.LogManager;
2324
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
2425
import org.elasticsearch.action.support.IndicesOptions;
2526
import org.elasticsearch.client.node.NodeClient;
2627
import org.elasticsearch.common.Strings;
28+
import org.elasticsearch.common.logging.DeprecationLogger;
2729
import org.elasticsearch.common.settings.Settings;
2830
import org.elasticsearch.rest.BaseRestHandler;
2931
import org.elasticsearch.rest.RestController;
3032
import org.elasticsearch.rest.RestRequest;
3133
import org.elasticsearch.rest.action.RestToXContentListener;
3234

3335
import java.io.IOException;
36+
import java.util.Collections;
3437
import java.util.Set;
38+
import java.util.stream.Collectors;
39+
import java.util.stream.Stream;
3540

3641
import static org.elasticsearch.rest.RestRequest.Method.GET;
3742
import static org.elasticsearch.rest.RestRequest.Method.HEAD;
@@ -41,6 +46,13 @@
4146
*/
4247
public class RestGetIndicesAction extends BaseRestHandler {
4348

49+
private static final DeprecationLogger deprecationLogger = new DeprecationLogger(LogManager.getLogger(RestGetIndicesAction.class));
50+
static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Using `include_type_name` in get indices requests is deprecated. "
51+
+ "The parameter will be removed in the next major version.";
52+
53+
private static final Set<String> allowedResponseParameters = Collections
54+
.unmodifiableSet(Stream.concat(Collections.singleton(INCLUDE_TYPE_NAME_PARAMETER).stream(), Settings.FORMAT_PARAMS.stream())
55+
.collect(Collectors.toSet()));
4456

4557
public RestGetIndicesAction(
4658
final Settings settings,
@@ -58,6 +70,10 @@ public String getName() {
5870
@Override
5971
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
6072
String[] indices = Strings.splitStringByCommaToArray(request.param("index"));
73+
// starting with 7.0 we don't include types by default in the response
74+
if (request.hasParam(INCLUDE_TYPE_NAME_PARAMETER)) {
75+
deprecationLogger.deprecatedAndMaybeLog("get_indices_with_types", TYPES_DEPRECATION_MESSAGE);
76+
}
6177
final GetIndexRequest getIndexRequest = new GetIndexRequest();
6278
getIndexRequest.indices(indices);
6379
getIndexRequest.indicesOptions(IndicesOptions.fromRequest(request, getIndexRequest.indicesOptions()));
@@ -68,9 +84,12 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
6884
return channel -> client.admin().indices().getIndex(getIndexRequest, new RestToXContentListener<>(channel));
6985
}
7086

87+
/**
88+
* Parameters used for controlling the response and thus might not be consumed during
89+
* preparation of the request execution in {@link BaseRestHandler#prepareRequest(RestRequest, NodeClient)}.
90+
*/
7191
@Override
7292
protected Set<String> responseParams() {
73-
return Settings.FORMAT_PARAMS;
93+
return allowedResponseParameters;
7494
}
75-
7695
}

0 commit comments

Comments
 (0)