Skip to content

Commit a6f2869

Browse files
catalin-ursachijavanna
authored andcommitted
Added Put Mapping API to high-level Rest client (#27869)
Relates to #27205
1 parent 0cb48cf commit a6f2869

File tree

13 files changed

+481
-11
lines changed

13 files changed

+481
-11
lines changed

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
2828
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
2929
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
30+
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
31+
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
3032
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
3133
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
3234

@@ -89,6 +91,29 @@ public void createAsync(CreateIndexRequest createIndexRequest, ActionListener<Cr
8991
listener, Collections.emptySet(), headers);
9092
}
9193

94+
/**
95+
* Updates the mappings on an index using the Put Mapping API
96+
* <p>
97+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html">
98+
* Put Mapping API on elastic.co</a>
99+
*/
100+
public PutMappingResponse putMapping(PutMappingRequest putMappingRequest, Header... headers) throws IOException {
101+
return restHighLevelClient.performRequestAndParseEntity(putMappingRequest, Request::putMapping, PutMappingResponse::fromXContent,
102+
Collections.emptySet(), headers);
103+
}
104+
105+
/**
106+
* Asynchronously updates the mappings on an index using the Put Mapping API
107+
* <p>
108+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html">
109+
* Put Mapping API on elastic.co</a>
110+
*/
111+
public void putMappingAsync(PutMappingRequest putMappingRequest, ActionListener<PutMappingResponse> listener,
112+
Header... headers) {
113+
restHighLevelClient.performRequestAsyncAndParseEntity(putMappingRequest, Request::putMapping, PutMappingResponse::fromXContent,
114+
listener, Collections.emptySet(), headers);
115+
}
116+
92117
/**
93118
* Opens an index using the Open Index API
94119
* <p>

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
3333
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
3434
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
35+
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
3536
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
3637
import org.elasticsearch.action.bulk.BulkRequest;
3738
import org.elasticsearch.action.delete.DeleteRequest;
@@ -179,6 +180,22 @@ static Request createIndex(CreateIndexRequest createIndexRequest) throws IOExcep
179180
return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity);
180181
}
181182

183+
static Request putMapping(PutMappingRequest putMappingRequest) throws IOException {
184+
// The concreteIndex is an internal concept, not applicable to requests made over the REST API.
185+
if (putMappingRequest.getConcreteIndex() != null) {
186+
throw new IllegalArgumentException("concreteIndex cannot be set on PutMapping requests made over the REST API");
187+
}
188+
189+
String endpoint = endpoint(putMappingRequest.indices(), "_mapping", putMappingRequest.type());
190+
191+
Params parameters = Params.builder();
192+
parameters.withTimeout(putMappingRequest.timeout());
193+
parameters.withMasterTimeout(putMappingRequest.masterNodeTimeout());
194+
195+
HttpEntity entity = createEntity(putMappingRequest, REQUEST_BODY_CONTENT_TYPE);
196+
return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity);
197+
}
198+
182199
static Request info() {
183200
return new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null);
184201
}
@@ -455,6 +472,10 @@ static String endpoint(String[] indices, String[] types, String endpoint) {
455472
return endpoint(String.join(",", indices), String.join(",", types), endpoint);
456473
}
457474

475+
static String endpoint(String[] indices, String endpoint, String type) {
476+
return endpoint(String.join(",", indices), endpoint, type);
477+
}
478+
458479
/**
459480
* Utility method to build request's endpoint.
460481
*/

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
2828
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
2929
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
30+
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
31+
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
3032
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
3133
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
3234
import org.elasticsearch.action.support.ActiveShardCount;
@@ -109,6 +111,35 @@ public void testCreateIndex() throws IOException {
109111
}
110112
}
111113

114+
@SuppressWarnings("unchecked")
115+
public void testPutMapping() throws IOException {
116+
{
117+
// Add mappings to index
118+
String indexName = "mapping_index";
119+
createIndex(indexName);
120+
121+
PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
122+
putMappingRequest.type("type_name");
123+
XContentBuilder mappingBuilder = JsonXContent.contentBuilder();
124+
mappingBuilder.startObject().startObject("properties").startObject("field");
125+
mappingBuilder.field("type", "text");
126+
mappingBuilder.endObject().endObject().endObject();
127+
putMappingRequest.source(mappingBuilder);
128+
129+
PutMappingResponse putMappingResponse =
130+
execute(putMappingRequest, highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync);
131+
assertTrue(putMappingResponse.isAcknowledged());
132+
133+
Map<String, Object> indexMetaData = getIndexMetadata(indexName);
134+
Map<String, Object> mappingsData = (Map) indexMetaData.get("mappings");
135+
Map<String, Object> typeData = (Map) mappingsData.get("type_name");
136+
Map<String, Object> properties = (Map) typeData.get("properties");
137+
Map<String, Object> field = (Map) properties.get("field");
138+
139+
assertEquals("text", field.get("type"));
140+
}
141+
}
142+
112143
public void testDeleteIndex() throws IOException {
113144
{
114145
// Delete index if exists

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
2929
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
3030
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
31+
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
3132
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
3233
import org.elasticsearch.action.bulk.BulkRequest;
3334
import org.elasticsearch.action.bulk.BulkShardRequest;
@@ -325,6 +326,39 @@ public void testCreateIndex() throws IOException {
325326
assertToXContentBody(createIndexRequest, request.getEntity());
326327
}
327328

329+
public void testPutMapping() throws IOException {
330+
PutMappingRequest putMappingRequest = new PutMappingRequest();
331+
332+
int numIndices = randomIntBetween(0, 5);
333+
String[] indices = new String[numIndices];
334+
for (int i = 0; i < numIndices; i++) {
335+
indices[i] = "index-" + randomAlphaOfLengthBetween(2, 5);
336+
}
337+
putMappingRequest.indices(indices);
338+
339+
String type = randomAlphaOfLengthBetween(3, 10);
340+
putMappingRequest.type(type);
341+
342+
Map<String, String> expectedParams = new HashMap<>();
343+
344+
setRandomTimeout(putMappingRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams);
345+
setRandomMasterTimeout(putMappingRequest, expectedParams);
346+
347+
Request request = Request.putMapping(putMappingRequest);
348+
StringJoiner endpoint = new StringJoiner("/", "/", "");
349+
String index = String.join(",", indices);
350+
if (Strings.hasLength(index)) {
351+
endpoint.add(index);
352+
}
353+
endpoint.add("_mapping");
354+
endpoint.add(type);
355+
assertEquals(endpoint.toString(), request.getEndpoint());
356+
357+
assertEquals(expectedParams, request.getParameters());
358+
assertEquals("PUT", request.getMethod());
359+
assertToXContentBody(putMappingRequest, request.getEntity());
360+
}
361+
328362
public void testDeleteIndex() {
329363
String[] indices = randomIndicesNames(0, 5);
330364
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indices);

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

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
2929
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
3030
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
31+
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
32+
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
3133
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
3234
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
3335
import org.elasticsearch.action.support.ActiveShardCount;
@@ -157,15 +159,15 @@ public void testCreateIndex() throws IOException {
157159

158160
// tag::create-index-request-mappings
159161
request.mapping("tweet", // <1>
160-
" {\n" +
161-
" \"tweet\": {\n" +
162-
" \"properties\": {\n" +
163-
" \"message\": {\n" +
164-
" \"type\": \"text\"\n" +
165-
" }\n" +
162+
"{\n" +
163+
" \"tweet\": {\n" +
164+
" \"properties\": {\n" +
165+
" \"message\": {\n" +
166+
" \"type\": \"text\"\n" +
166167
" }\n" +
167168
" }\n" +
168-
" }", // <2>
169+
" }\n" +
170+
"}", // <2>
169171
XContentType.JSON);
170172
// end::create-index-request-mappings
171173

@@ -228,6 +230,86 @@ public void onFailure(Exception e) {
228230
}
229231
}
230232

233+
public void testPutMapping() throws IOException {
234+
RestHighLevelClient client = highLevelClient();
235+
236+
{
237+
CreateIndexResponse createIndexResponse = client.indices().create(new CreateIndexRequest("twitter"));
238+
assertTrue(createIndexResponse.isAcknowledged());
239+
}
240+
241+
{
242+
// tag::put-mapping-request
243+
PutMappingRequest request = new PutMappingRequest("twitter"); // <1>
244+
request.type("tweet"); // <2>
245+
// end::put-mapping-request
246+
247+
// tag::put-mapping-request-source
248+
request.source(
249+
"{\n" +
250+
" \"tweet\": {\n" +
251+
" \"properties\": {\n" +
252+
" \"message\": {\n" +
253+
" \"type\": \"text\"\n" +
254+
" }\n" +
255+
" }\n" +
256+
" }\n" +
257+
"}", // <1>
258+
XContentType.JSON);
259+
// end::put-mapping-request-source
260+
261+
// tag::put-mapping-request-timeout
262+
request.timeout(TimeValue.timeValueMinutes(2)); // <1>
263+
request.timeout("2m"); // <2>
264+
// end::put-mapping-request-timeout
265+
// tag::put-mapping-request-masterTimeout
266+
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
267+
request.masterNodeTimeout("1m"); // <2>
268+
// end::put-mapping-request-masterTimeout
269+
270+
// tag::put-mapping-execute
271+
PutMappingResponse putMappingResponse = client.indices().putMapping(request);
272+
// end::put-mapping-execute
273+
274+
// tag::put-mapping-response
275+
boolean acknowledged = putMappingResponse.isAcknowledged(); // <1>
276+
// end::put-mapping-response
277+
assertTrue(acknowledged);
278+
}
279+
}
280+
281+
public void testPutMappingAsync() throws Exception {
282+
final RestHighLevelClient client = highLevelClient();
283+
284+
{
285+
CreateIndexResponse createIndexResponse = client.indices().create(new CreateIndexRequest("twitter"));
286+
assertTrue(createIndexResponse.isAcknowledged());
287+
}
288+
289+
{
290+
PutMappingRequest request = new PutMappingRequest("twitter").type("tweet");
291+
// tag::put-mapping-execute-async
292+
client.indices().putMappingAsync(request, new ActionListener<PutMappingResponse>() {
293+
@Override
294+
public void onResponse(PutMappingResponse putMappingResponse) {
295+
// <1>
296+
}
297+
298+
@Override
299+
public void onFailure(Exception e) {
300+
// <2>
301+
}
302+
});
303+
// end::put-mapping-execute-async
304+
305+
assertBusy(() -> {
306+
// TODO Use Indices Exist API instead once it exists
307+
Response response = client.getLowLevelClient().performRequest("HEAD", "twitter");
308+
assertTrue(RestStatus.OK.getStatus() == response.getStatusLine().getStatusCode());
309+
});
310+
}
311+
}
312+
231313
public void testOpenIndex() throws IOException {
232314
RestHighLevelClient client = highLevelClient();
233315

docs/java-rest/high-level/apis/index.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ include::open_index.asciidoc[]
66

77
include::close_index.asciidoc[]
88

9+
include::putmapping.asciidoc[]
10+
911
include::_index.asciidoc[]
1012

1113
include::get.asciidoc[]
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
[[java-rest-high-put-mapping]]
2+
=== Put Mapping API
3+
4+
[[java-rest-high-put-mapping-request]]
5+
==== Put Mapping Request
6+
7+
A `PutMappingRequest` requires an `index` argument, and a type:
8+
9+
["source","java",subs="attributes,callouts,macros"]
10+
--------------------------------------------------
11+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-request]
12+
--------------------------------------------------
13+
<1> The index to add the mapping to
14+
<2> The type to create (or update)
15+
16+
==== Mapping source
17+
A description of the fields to create on the mapping; if not defined, the mapping will default to empty.
18+
19+
["source","java",subs="attributes,callouts,macros"]
20+
--------------------------------------------------
21+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-request-source]
22+
--------------------------------------------------
23+
<1> The mapping source
24+
25+
==== Optional arguments
26+
The following arguments can optionally be provided:
27+
28+
["source","java",subs="attributes,callouts,macros"]
29+
--------------------------------------------------
30+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-request-timeout]
31+
--------------------------------------------------
32+
<1> Timeout to wait for the all the nodes to acknowledge the index creation as a `TimeValue`
33+
<2> Timeout to wait for the all the nodes to acknowledge the index creation as a `String`
34+
35+
["source","java",subs="attributes,callouts,macros"]
36+
--------------------------------------------------
37+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-request-masterTimeout]
38+
--------------------------------------------------
39+
<1> Timeout to connect to the master node as a `TimeValue`
40+
<2> Timeout to connect to the master node as a `String`
41+
42+
[[java-rest-high-put-mapping-sync]]
43+
==== Synchronous Execution
44+
45+
["source","java",subs="attributes,callouts,macros"]
46+
--------------------------------------------------
47+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-execute]
48+
--------------------------------------------------
49+
50+
[[java-rest-high-put-mapping-async]]
51+
==== Asynchronous Execution
52+
53+
["source","java",subs="attributes,callouts,macros"]
54+
--------------------------------------------------
55+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-execute-async]
56+
--------------------------------------------------
57+
<1> Called when the execution is successfully completed. The response is
58+
provided as an argument
59+
<2> Called in case of failure. The raised exception is provided as an argument
60+
61+
[[java-rest-high-put-mapping-response]]
62+
==== Put Mapping Response
63+
64+
The returned `PutMappingResponse` allows to retrieve information about the executed
65+
operation as follows:
66+
67+
["source","java",subs="attributes,callouts,macros"]
68+
--------------------------------------------------
69+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-response]
70+
--------------------------------------------------
71+
<1> Indicates whether all of the nodes have acknowledged the request

docs/java-rest/high-level/supported-apis.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Indices APIs::
88
* <<java-rest-high-delete-index>>
99
* <<java-rest-high-open-index>>
1010
* <<java-rest-high-close-index>>
11+
* <<java-rest-high-put-mapping>>
1112

1213
Single document APIs::
1314
* <<java-rest-high-document-index>>

0 commit comments

Comments
 (0)