Skip to content

Commit 24e3019

Browse files
authored
Deprecate types in put mapping (backport to 6.x). (#37627)
From previous PRs, the `include_type_name` parameter was already present and defaulted to true. This PR makes the following updates: - Add deprecation warnings to `RestPutMappingAction`, plus tests in `RestPutMappingActionTests`. - Add a typeless 'put mappings' method to the Java HLRC, and deprecate the old typed version. To do this cleanly, I opted to create a new `PutMappingRequest` object that differs from the existing server one.
1 parent c6ca57a commit 24e3019

File tree

15 files changed

+543
-130
lines changed

15 files changed

+543
-130
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse;
4343
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
4444
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
45-
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
4645
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
4746
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
4847
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
@@ -64,6 +63,7 @@
6463
import org.elasticsearch.client.indices.FreezeIndexRequest;
6564
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
6665
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
66+
import org.elasticsearch.client.indices.PutMappingRequest;
6767
import org.elasticsearch.client.indices.UnfreezeIndexRequest;
6868
import org.elasticsearch.rest.RestStatus;
6969

@@ -210,14 +210,37 @@ public AcknowledgedResponse putMapping(PutMappingRequest putMappingRequest, Requ
210210
* <p>
211211
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html">
212212
* Put Mapping API on elastic.co</a>
213-
* @deprecated Prefer {@link #putMapping(PutMappingRequest, RequestOptions)}
213+
*
214+
* @deprecated This method uses an old request object which still refers to types, a deprecated feature. The
215+
* method {@link #putMapping(PutMappingRequest, RequestOptions)} should be used instead, which accepts a new
216+
* request object, and also uses request options instead of headers.
214217
*/
215218
@Deprecated
216-
public AcknowledgedResponse putMapping(PutMappingRequest putMappingRequest, Header... headers) throws IOException {
219+
public AcknowledgedResponse putMapping(org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest,
220+
Header... headers) throws IOException {
217221
return restHighLevelClient.performRequestAndParseEntity(putMappingRequest, IndicesRequestConverters::putMapping,
218222
AcknowledgedResponse::fromXContent, emptySet(), headers);
219223
}
220224

225+
/**
226+
* Updates the mappings on an index using the Put Mapping API.
227+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html">
228+
* Put Mapping API on elastic.co</a>
229+
* @param putMappingRequest the request
230+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
231+
* @return the response
232+
* @throws IOException in case there is a problem sending the request or parsing back the response
233+
*
234+
* @deprecated This method uses an old request object which still refers to types, a deprecated feature. The method
235+
* {@link #putMapping(PutMappingRequest, RequestOptions)} should be used instead, which accepts a new request object.
236+
*/
237+
@Deprecated
238+
public AcknowledgedResponse putMapping(org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest,
239+
RequestOptions options) throws IOException {
240+
return restHighLevelClient.performRequestAndParseEntity(putMappingRequest, IndicesRequestConverters::putMapping, options,
241+
AcknowledgedResponse::fromXContent, emptySet());
242+
}
243+
221244
/**
222245
* Asynchronously updates the mappings on an index using the Put Mapping API.
223246
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html">
@@ -237,13 +260,37 @@ public void putMappingAsync(PutMappingRequest putMappingRequest, RequestOptions
237260
* <p>
238261
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html">
239262
* Put Mapping API on elastic.co</a>
240-
* @deprecated Prefer {@link #putMappingAsync(PutMappingRequest, RequestOptions, ActionListener)}
263+
*
264+
* @deprecated This method uses an old request object which still refers to types, a deprecated feature. The
265+
* method {@link #putMappingAsync(PutMappingRequest, RequestOptions, ActionListener)} should be used instead,
266+
* which accepts a new request object, and also uses request options instead of headers.
241267
*/
242268
@Deprecated
243-
public void putMappingAsync(PutMappingRequest putMappingRequest, ActionListener<AcknowledgedResponse> listener,
269+
public void putMappingAsync(org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest,
270+
ActionListener<AcknowledgedResponse> listener,
244271
Header... headers) {
245272
restHighLevelClient.performRequestAsyncAndParseEntity(putMappingRequest, IndicesRequestConverters::putMapping,
246-
AcknowledgedResponse::fromXContent, listener, emptySet(), headers);
273+
AcknowledgedResponse::fromXContent, listener, emptySet(), headers);
274+
}
275+
276+
/**
277+
* Asynchronously updates the mappings on an index using the Put Mapping API.
278+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html">
279+
* Put Mapping API on elastic.co</a>
280+
* @param putMappingRequest the request
281+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
282+
* @param listener the listener to be notified upon request completion
283+
*
284+
* @deprecated This method uses an old request object which still refers to types, a deprecated feature. The
285+
* method {@link #putMappingAsync(PutMappingRequest, RequestOptions, ActionListener)} should be used instead,
286+
* which accepts a new request object.
287+
*/
288+
@Deprecated
289+
public void putMappingAsync(org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest,
290+
RequestOptions options,
291+
ActionListener<AcknowledgedResponse> listener) {
292+
restHighLevelClient.performRequestAsyncAndParseEntity(putMappingRequest, IndicesRequestConverters::putMapping, options,
293+
AcknowledgedResponse::fromXContent, listener, emptySet());
247294
}
248295

249296
/**

client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesRequestConverters.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
3838
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest;
3939
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
40-
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
4140
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
4241
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
4342
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
@@ -52,12 +51,15 @@
5251
import org.elasticsearch.client.indices.FreezeIndexRequest;
5352
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
5453
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
54+
import org.elasticsearch.client.indices.PutMappingRequest;
5555
import org.elasticsearch.client.indices.UnfreezeIndexRequest;
5656
import org.elasticsearch.common.Strings;
5757

5858
import java.io.IOException;
5959
import java.util.Locale;
6060

61+
import static org.elasticsearch.rest.BaseRestHandler.INCLUDE_TYPE_NAME_PARAMETER;
62+
6163
final class IndicesRequestConverters {
6264

6365
private IndicesRequestConverters() {}
@@ -121,13 +123,25 @@ static Request updateAliases(IndicesAliasesRequest indicesAliasesRequest) throws
121123
}
122124

123125
static Request putMapping(PutMappingRequest putMappingRequest) throws IOException {
126+
Request request = new Request(HttpPut.METHOD_NAME, RequestConverters.endpoint(putMappingRequest.indices(), "_mapping"));
127+
128+
RequestConverters.Params parameters = new RequestConverters.Params(request);
129+
parameters.withTimeout(putMappingRequest.timeout());
130+
parameters.withMasterTimeout(putMappingRequest.masterNodeTimeout());
131+
parameters.putParam(INCLUDE_TYPE_NAME_PARAMETER, "false");
132+
133+
request.setEntity(RequestConverters.createEntity(putMappingRequest, RequestConverters.REQUEST_BODY_CONTENT_TYPE));
134+
return request;
135+
}
136+
137+
static Request putMapping(org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest) throws IOException {
124138
// The concreteIndex is an internal concept, not applicable to requests made over the REST API.
125139
if (putMappingRequest.getConcreteIndex() != null) {
126140
throw new IllegalArgumentException("concreteIndex cannot be set on PutMapping requests made over the REST API");
127141
}
128142

129-
Request request = new Request(HttpPut.METHOD_NAME, RequestConverters.endpoint(putMappingRequest.indices(), "_mapping",
130-
putMappingRequest.type()));
143+
Request request = new Request(HttpPut.METHOD_NAME, RequestConverters.endpoint(putMappingRequest.indices(),
144+
"_mapping", putMappingRequest.type()));
131145

132146
RequestConverters.Params parameters = new RequestConverters.Params(request);
133147
parameters.withTimeout(putMappingRequest.timeout());
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client.indices;
21+
22+
import org.elasticsearch.ElasticsearchGenerationException;
23+
import org.elasticsearch.action.IndicesRequest;
24+
import org.elasticsearch.action.support.IndicesOptions;
25+
import org.elasticsearch.client.TimedRequest;
26+
import org.elasticsearch.common.bytes.BytesArray;
27+
import org.elasticsearch.common.bytes.BytesReference;
28+
import org.elasticsearch.common.xcontent.ToXContent;
29+
import org.elasticsearch.common.xcontent.ToXContentObject;
30+
import org.elasticsearch.common.xcontent.XContentBuilder;
31+
import org.elasticsearch.common.xcontent.XContentFactory;
32+
import org.elasticsearch.common.xcontent.XContentType;
33+
34+
import java.io.IOException;
35+
import java.io.InputStream;
36+
import java.util.Map;
37+
38+
/**
39+
* Put a mapping definition into one or more indices. If an index already contains mappings,
40+
* the new mappings will be merged with the existing one. If there are elements that cannot
41+
* be merged, the request will be rejected.
42+
*/
43+
public class PutMappingRequest extends TimedRequest implements IndicesRequest, ToXContentObject {
44+
45+
private final String[] indices;
46+
private IndicesOptions indicesOptions = IndicesOptions.fromOptions(false, false, true, true);
47+
48+
private BytesReference source;
49+
private XContentType xContentType;
50+
51+
/**
52+
* Constructs a new put mapping request against one or more indices. If no indices
53+
* are provided then it will be executed against all indices.
54+
*/
55+
public PutMappingRequest(String... indices) {
56+
this.indices = indices;
57+
}
58+
59+
/**
60+
* The indices into which the mappings will be put.
61+
*/
62+
@Override
63+
public String[] indices() {
64+
return indices;
65+
}
66+
67+
@Override
68+
public IndicesOptions indicesOptions() {
69+
return indicesOptions;
70+
}
71+
72+
public PutMappingRequest indicesOptions(IndicesOptions indicesOptions) {
73+
this.indicesOptions = indicesOptions;
74+
return this;
75+
}
76+
77+
/**
78+
* The mapping source definition.
79+
*/
80+
public BytesReference source() {
81+
return source;
82+
}
83+
84+
/**
85+
* The {@link XContentType} of the mapping source.
86+
*/
87+
public XContentType xContentType() {
88+
return xContentType;
89+
}
90+
91+
/**
92+
* The mapping source definition.
93+
*
94+
* Note that the definition should *not* be nested under a type name.
95+
*/
96+
public PutMappingRequest source(Map<String, ?> mappingSource) {
97+
try {
98+
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON);
99+
builder.map(mappingSource);
100+
return source(builder);
101+
} catch (IOException e) {
102+
throw new ElasticsearchGenerationException("Failed to generate [" + mappingSource + "]", e);
103+
}
104+
}
105+
106+
/**
107+
* The mapping source definition.
108+
*
109+
* Note that the definition should *not* be nested under a type name.
110+
*/
111+
public PutMappingRequest source(String mappingSource, XContentType xContentType) {
112+
this.source = new BytesArray(mappingSource);
113+
this.xContentType = xContentType;
114+
return this;
115+
}
116+
117+
/**
118+
* The mapping source definition.
119+
*
120+
* Note that the definition should *not* be nested under a type name.
121+
*/
122+
public PutMappingRequest source(XContentBuilder builder) {
123+
this.source = BytesReference.bytes(builder);
124+
this.xContentType = builder.contentType();
125+
return this;
126+
}
127+
128+
/**
129+
* The mapping source definition.
130+
*
131+
* Note that the definition should *not* be nested under a type name.
132+
*/
133+
public PutMappingRequest source(BytesReference source, XContentType xContentType) {
134+
this.source = source;
135+
this.xContentType = xContentType;
136+
return this;
137+
}
138+
139+
@Override
140+
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
141+
if (source != null) {
142+
try (InputStream stream = source.streamInput()) {
143+
builder.rawValue(stream, xContentType);
144+
}
145+
} else {
146+
builder.startObject().endObject();
147+
}
148+
return builder;
149+
}
150+
}

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

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse;
4848
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
4949
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
50-
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
5150
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
5251
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
5352
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
@@ -75,6 +74,7 @@
7574
import org.elasticsearch.client.indices.FreezeIndexRequest;
7675
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
7776
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
77+
import org.elasticsearch.client.indices.PutMappingRequest;
7878
import org.elasticsearch.client.indices.UnfreezeIndexRequest;
7979
import org.elasticsearch.cluster.metadata.AliasMetaData;
8080
import org.elasticsearch.cluster.metadata.IndexMetaData;
@@ -94,6 +94,7 @@
9494
import org.elasticsearch.index.query.QueryBuilder;
9595
import org.elasticsearch.index.query.QueryBuilders;
9696
import org.elasticsearch.rest.RestStatus;
97+
import org.elasticsearch.rest.action.admin.indices.RestPutMappingAction;
9798

9899
import java.io.IOException;
99100
import java.util.Arrays;
@@ -413,33 +414,56 @@ public void testGetIndexNonExistentIndex() throws IOException {
413414
}
414415

415416
public void testPutMapping() throws IOException {
416-
// Add mappings to index
417417
String indexName = "mapping_index";
418418
createIndex(indexName, Settings.EMPTY);
419419

420420
PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
421-
putMappingRequest.type("_doc");
422421
XContentBuilder mappingBuilder = JsonXContent.contentBuilder();
423422
mappingBuilder.startObject().startObject("properties").startObject("field");
424423
mappingBuilder.field("type", "text");
425424
mappingBuilder.endObject().endObject().endObject();
426425
putMappingRequest.source(mappingBuilder);
427426

428-
AcknowledgedResponse putMappingResponse =
429-
execute(putMappingRequest, highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync,
430-
highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync);
427+
AcknowledgedResponse putMappingResponse = execute(putMappingRequest,
428+
highLevelClient().indices()::putMapping,
429+
highLevelClient().indices()::putMappingAsync);
431430
assertTrue(putMappingResponse.isAcknowledged());
432431

433432
Map<String, Object> getIndexResponse = getAsMap(indexName);
434-
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings._doc.properties.field.type", getIndexResponse));
433+
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings._doc.properties.field.type",
434+
getIndexResponse));
435+
}
436+
437+
public void testPutMappingWithTypes() throws IOException {
438+
String indexName = "mapping_index";
439+
createIndex(indexName, Settings.EMPTY);
440+
441+
org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest =
442+
new org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest(indexName);
443+
putMappingRequest.type("some_type");
444+
445+
XContentBuilder mappingBuilder = JsonXContent.contentBuilder();
446+
mappingBuilder.startObject().startObject("properties").startObject("field");
447+
mappingBuilder.field("type", "text");
448+
mappingBuilder.endObject().endObject().endObject();
449+
putMappingRequest.source(mappingBuilder);
450+
451+
AcknowledgedResponse putMappingResponse = execute(putMappingRequest,
452+
highLevelClient().indices()::putMapping,
453+
highLevelClient().indices()::putMappingAsync,
454+
expectWarnings(RestPutMappingAction.TYPES_DEPRECATION_MESSAGE));
455+
assertTrue(putMappingResponse.isAcknowledged());
456+
457+
Map<String, Object> getIndexResponse = getAsMap(indexName);
458+
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.some_type.properties.field.type",
459+
getIndexResponse));
435460
}
436461

437462
public void testGetMapping() throws IOException {
438463
String indexName = "test";
439464
createIndex(indexName, Settings.EMPTY);
440465

441466
PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
442-
putMappingRequest.type("_doc");
443467
XContentBuilder mappingBuilder = JsonXContent.contentBuilder();
444468
mappingBuilder.startObject().startObject("properties").startObject("field");
445469
mappingBuilder.field("type", "text");
@@ -475,7 +499,6 @@ public void testGetFieldMapping() throws IOException {
475499
createIndex(indexName, Settings.EMPTY);
476500

477501
PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
478-
putMappingRequest.type("_doc");
479502
XContentBuilder mappingBuilder = JsonXContent.contentBuilder();
480503
mappingBuilder.startObject().startObject("properties").startObject("field");
481504
mappingBuilder.field("type", "text");

0 commit comments

Comments
 (0)