Skip to content

Commit 1a3eac0

Browse files
author
Vladimir Dolzhenko
committed
Add get field mappings to High Level REST API Client
Relates to #27205 (cherry picked from commit b7ef75f)
1 parent a55bdff commit 1a3eac0

File tree

9 files changed

+562
-8
lines changed

9 files changed

+562
-8
lines changed

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest;
3939
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse;
4040
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
41+
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest;
42+
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse;
4143
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
4244
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
4345
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
@@ -268,6 +270,35 @@ public void getMappingsAsync(GetMappingsRequest getMappingsRequest, RequestOptio
268270
GetMappingsResponse::fromXContent, listener, emptySet());
269271
}
270272

273+
/**
274+
* Retrieves the field mappings on an index or indices using the Get Field Mapping API.
275+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html">
276+
* Get Field Mapping API on elastic.co</a>
277+
* @param getFieldMappingsRequest the request
278+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
279+
* @return the response
280+
* @throws IOException in case there is a problem sending the request or parsing back the response
281+
*/
282+
public GetFieldMappingsResponse getFieldMapping(GetFieldMappingsRequest getFieldMappingsRequest,
283+
RequestOptions options) throws IOException {
284+
return restHighLevelClient.performRequestAndParseEntity(getFieldMappingsRequest, RequestConverters::getFieldMapping, options,
285+
GetFieldMappingsResponse::fromXContent, emptySet());
286+
}
287+
288+
/**
289+
* Asynchronously retrieves the field mappings on an index on indices using the Get Field Mapping API.
290+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html">
291+
* Get Field Mapping API on elastic.co</a>
292+
* @param getFieldMappingsRequest the request
293+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
294+
* @param listener the listener to be notified upon request completion
295+
*/
296+
public void getFieldMappingAsync(GetFieldMappingsRequest getFieldMappingsRequest, RequestOptions options,
297+
ActionListener<GetFieldMappingsResponse> listener) {
298+
restHighLevelClient.performRequestAsyncAndParseEntity(getFieldMappingsRequest, RequestConverters::getFieldMapping, options,
299+
GetFieldMappingsResponse::fromXContent, listener, emptySet());
300+
}
301+
271302
/**
272303
* Updates aliases using the Index Aliases API.
273304
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html">

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest;
5151
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest;
5252
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
53+
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest;
5354
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
5455
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
5556
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
@@ -232,6 +233,25 @@ static Request getMappings(GetMappingsRequest getMappingsRequest) throws IOExcep
232233
return request;
233234
}
234235

236+
static Request getFieldMapping(GetFieldMappingsRequest getFieldMappingsRequest) throws IOException {
237+
String[] indices = getFieldMappingsRequest.indices() == null ? Strings.EMPTY_ARRAY : getFieldMappingsRequest.indices();
238+
String[] types = getFieldMappingsRequest.types() == null ? Strings.EMPTY_ARRAY : getFieldMappingsRequest.types();
239+
String[] fields = getFieldMappingsRequest.fields() == null ? Strings.EMPTY_ARRAY : getFieldMappingsRequest.fields();
240+
241+
String endpoint = new EndpointBuilder().addCommaSeparatedPathParts(indices)
242+
.addPathPartAsIs("_mapping").addCommaSeparatedPathParts(types)
243+
.addPathPartAsIs("field").addCommaSeparatedPathParts(fields)
244+
.build();
245+
246+
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
247+
248+
Params parameters = new Params(request);
249+
parameters.withIndicesOptions(getFieldMappingsRequest.indicesOptions());
250+
parameters.withIncludeDefaults(getFieldMappingsRequest.includeDefaults());
251+
parameters.withLocal(getFieldMappingsRequest.local());
252+
return request;
253+
}
254+
235255
static Request refresh(RefreshRequest refreshRequest) {
236256
String[] indices = refreshRequest.indices() == null ? Strings.EMPTY_ARRAY : refreshRequest.indices();
237257
Request request = new Request(HttpPost.METHOD_NAME, endpoint(indices, "_refresh"));

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest;
4444
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse;
4545
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
46+
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest;
47+
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse;
4648
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
4749
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
4850
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
@@ -75,6 +77,7 @@
7577
import org.elasticsearch.cluster.metadata.IndexMetaData;
7678
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
7779
import org.elasticsearch.common.ValidationException;
80+
import org.elasticsearch.common.bytes.BytesArray;
7881
import org.elasticsearch.common.settings.Setting;
7982
import org.elasticsearch.common.settings.Settings;
8083
import org.elasticsearch.common.unit.ByteSizeUnit;
@@ -388,6 +391,41 @@ public void testGetMapping() throws IOException {
388391
assertThat(mappings, equalTo(expected));
389392
}
390393

394+
public void testGetFieldMapping() throws IOException {
395+
String indexName = "test";
396+
createIndex(indexName, Settings.EMPTY);
397+
398+
PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
399+
putMappingRequest.type("_doc");
400+
XContentBuilder mappingBuilder = JsonXContent.contentBuilder();
401+
mappingBuilder.startObject().startObject("properties").startObject("field");
402+
mappingBuilder.field("type", "text");
403+
mappingBuilder.endObject().endObject().endObject();
404+
putMappingRequest.source(mappingBuilder);
405+
406+
PutMappingResponse putMappingResponse =
407+
execute(putMappingRequest, highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync);
408+
assertTrue(putMappingResponse.isAcknowledged());
409+
410+
GetFieldMappingsRequest getFieldMappingsRequest = new GetFieldMappingsRequest()
411+
.indices(indexName)
412+
.types("_doc")
413+
.fields("field");
414+
415+
GetFieldMappingsResponse getFieldMappingsResponse =
416+
execute(getFieldMappingsRequest,
417+
highLevelClient().indices()::getFieldMapping,
418+
highLevelClient().indices()::getFieldMappingAsync);
419+
420+
final Map<String, GetFieldMappingsResponse.FieldMappingMetaData> fieldMappingMap =
421+
getFieldMappingsResponse.mappings().get(indexName).get("_doc");
422+
423+
final GetFieldMappingsResponse.FieldMappingMetaData metaData =
424+
new GetFieldMappingsResponse.FieldMappingMetaData("field",
425+
new BytesArray("{\"field\":{\"type\":\"text\"}}"));
426+
assertThat(fieldMappingMap, equalTo(Collections.singletonMap("field", metaData)));
427+
}
428+
391429
public void testDeleteIndex() throws IOException {
392430
{
393431
// Delete index if exists

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

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import org.elasticsearch.action.admin.indices.flush.SyncedFlushRequest;
5353
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest;
5454
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
55+
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest;
5556
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
5657
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
5758
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
@@ -466,6 +467,61 @@ public void testGetMapping() throws IOException {
466467
assertThat(HttpGet.METHOD_NAME, equalTo(request.getMethod()));
467468
}
468469

470+
public void testGetFieldMapping() throws IOException {
471+
GetFieldMappingsRequest getFieldMappingsRequest = new GetFieldMappingsRequest();
472+
473+
String[] indices = Strings.EMPTY_ARRAY;
474+
if (randomBoolean()) {
475+
indices = randomIndicesNames(0, 5);
476+
getFieldMappingsRequest.indices(indices);
477+
} else if (randomBoolean()) {
478+
getFieldMappingsRequest.indices((String[]) null);
479+
}
480+
481+
String type = null;
482+
if (randomBoolean()) {
483+
type = randomAlphaOfLengthBetween(3, 10);
484+
getFieldMappingsRequest.types(type);
485+
} else if (randomBoolean()) {
486+
getFieldMappingsRequest.types((String[]) null);
487+
}
488+
489+
String[] fields = null;
490+
if (randomBoolean()) {
491+
fields = new String[randomIntBetween(1, 5)];
492+
for (int i = 0; i < fields.length; i++) {
493+
fields[i] = randomAlphaOfLengthBetween(3, 10);
494+
}
495+
getFieldMappingsRequest.fields(fields);
496+
} else if (randomBoolean()) {
497+
getFieldMappingsRequest.fields((String[]) null);
498+
}
499+
500+
Map<String, String> expectedParams = new HashMap<>();
501+
502+
setRandomIndicesOptions(getFieldMappingsRequest::indicesOptions, getFieldMappingsRequest::indicesOptions, expectedParams);
503+
setRandomLocal(getFieldMappingsRequest::local, expectedParams);
504+
505+
Request request = RequestConverters.getFieldMapping(getFieldMappingsRequest);
506+
StringJoiner endpoint = new StringJoiner("/", "/", "");
507+
String index = String.join(",", indices);
508+
if (Strings.hasLength(index)) {
509+
endpoint.add(index);
510+
}
511+
endpoint.add("_mapping");
512+
if (type != null) {
513+
endpoint.add(type);
514+
}
515+
endpoint.add("field");
516+
if (fields != null) {
517+
endpoint.add(String.join(",", fields));
518+
}
519+
assertThat(endpoint.toString(), equalTo(request.getEndpoint()));
520+
521+
assertThat(expectedParams, equalTo(request.getParameters()));
522+
assertThat(HttpGet.METHOD_NAME, equalTo(request.getMethod()));
523+
}
524+
469525
public void testDeleteIndex() {
470526
String[] indices = randomIndicesNames(0, 5);
471527
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indices);
@@ -2272,16 +2328,20 @@ private static void setRandomHumanReadable(GetIndexRequest request, Map<String,
22722328
}
22732329
}
22742330

2275-
private static void setRandomLocal(MasterNodeReadRequest<?> request, Map<String, String> expectedParams) {
2331+
private static void setRandomLocal(Consumer<Boolean> setter, Map<String, String> expectedParams) {
22762332
if (randomBoolean()) {
22772333
boolean local = randomBoolean();
2278-
request.local(local);
2334+
setter.accept(local);
22792335
if (local) {
22802336
expectedParams.put("local", String.valueOf(local));
22812337
}
22822338
}
22832339
}
22842340

2341+
private static void setRandomLocal(MasterNodeReadRequest<?> request, Map<String, String> expectedParams) {
2342+
setRandomLocal(request::local, expectedParams);
2343+
}
2344+
22852345
private static void setRandomTimeout(Consumer<String> setter, TimeValue defaultTimeout, Map<String, String> expectedParams) {
22862346
if (randomBoolean()) {
22872347
String timeout = randomTimeValue();

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

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest;
4242
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse;
4343
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
44+
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest;
45+
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse;
4446
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
4547
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
4648
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
@@ -703,6 +705,110 @@ public void onFailure(Exception e) {
703705
}
704706
}
705707

708+
public void testGetFieldMapping() throws IOException, InterruptedException {
709+
RestHighLevelClient client = highLevelClient();
710+
711+
{
712+
CreateIndexResponse createIndexResponse = client.indices().create(new CreateIndexRequest("twitter"), RequestOptions.DEFAULT);
713+
assertTrue(createIndexResponse.isAcknowledged());
714+
PutMappingRequest request = new PutMappingRequest("twitter");
715+
request.type("tweet");
716+
request.source(
717+
"{\n" +
718+
" \"properties\": {\n" +
719+
" \"message\": {\n" +
720+
" \"type\": \"text\"\n" +
721+
" },\n" +
722+
" \"timestamp\": {\n" +
723+
" \"type\": \"date\"\n" +
724+
" }\n" +
725+
" }\n" +
726+
"}", // <1>
727+
XContentType.JSON);
728+
PutMappingResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
729+
assertTrue(putMappingResponse.isAcknowledged());
730+
}
731+
732+
// tag::get-field-mapping-request
733+
GetFieldMappingsRequest request = new GetFieldMappingsRequest(); // <1>
734+
request.indices("twitter"); // <2>
735+
request.types("tweet"); // <3>
736+
request.fields("message", "timestamp"); // <4>
737+
// end::get-field-mapping-request
738+
739+
// tag::get-field-mapping-request-indicesOptions
740+
request.indicesOptions(IndicesOptions.lenientExpandOpen()); // <1>
741+
// end::get-field-mapping-request-indicesOptions
742+
743+
// tag::get-field-mapping-request-local
744+
request.local(true); // <1>
745+
// end::get-field-mapping-request-local
746+
747+
{
748+
749+
// tag::get-field-mapping-execute
750+
GetFieldMappingsResponse response =
751+
client.indices().getFieldMapping(request, RequestOptions.DEFAULT);
752+
// end::get-field-mapping-execute
753+
754+
// tag::get-field-mapping-response
755+
final Map<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetaData>>> mappings =
756+
response.mappings();// <1>
757+
final Map<String, GetFieldMappingsResponse.FieldMappingMetaData> typeMappings =
758+
mappings.get("twitter").get("tweet"); // <2>
759+
final GetFieldMappingsResponse.FieldMappingMetaData metaData =
760+
typeMappings.get("message");// <3>
761+
762+
final String fullName = metaData.fullName();// <4>
763+
final Map<String, Object> source = metaData.sourceAsMap(); // <5>
764+
// end::get-field-mapping-response
765+
}
766+
767+
{
768+
// tag::get-field-mapping-execute-listener
769+
ActionListener<GetFieldMappingsResponse> listener =
770+
new ActionListener<GetFieldMappingsResponse>() {
771+
@Override
772+
public void onResponse(GetFieldMappingsResponse putMappingResponse) {
773+
// <1>
774+
}
775+
776+
@Override
777+
public void onFailure(Exception e) {
778+
// <2>
779+
}
780+
};
781+
// end::get-field-mapping-execute-listener
782+
783+
// Replace the empty listener by a blocking listener in test
784+
final CountDownLatch latch = new CountDownLatch(1);
785+
final ActionListener<GetFieldMappingsResponse> latchListener = new LatchedActionListener<>(listener, latch);
786+
listener = ActionListener.wrap(r -> {
787+
final Map<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetaData>>> mappings =
788+
r.mappings();
789+
final Map<String, GetFieldMappingsResponse.FieldMappingMetaData> typeMappings =
790+
mappings.get("twitter").get("tweet");
791+
final GetFieldMappingsResponse.FieldMappingMetaData metaData1 = typeMappings.get("message");
792+
793+
final String fullName = metaData1.fullName();
794+
final Map<String, Object> source = metaData1.sourceAsMap();
795+
latchListener.onResponse(r);
796+
}, e -> {
797+
latchListener.onFailure(e);
798+
fail("should not fail");
799+
});
800+
801+
// tag::get-field-mapping-execute-async
802+
client.indices().getFieldMappingAsync(request, RequestOptions.DEFAULT, listener); // <1>
803+
// end::get-field-mapping-execute-async
804+
805+
assertTrue(latch.await(30L, TimeUnit.SECONDS));
806+
}
807+
808+
809+
}
810+
811+
706812
public void testOpenIndex() throws Exception {
707813
RestHighLevelClient client = highLevelClient();
708814

0 commit comments

Comments
 (0)