From e9e08f7a8971494f2d32d4badf296f97ecf40183 Mon Sep 17 00:00:00 2001 From: Sohaib Iftikhar Date: Sat, 30 Jun 2018 04:13:31 +0200 Subject: [PATCH] REST high-level client: add get index API Relates to #27205 --- .../elasticsearch/client/IndicesClient.java | 29 ++++++ .../client/RequestConverters.java | 16 ++++ .../elasticsearch/client/IndicesClientIT.java | 72 +++++++++++++++ .../client/RequestConvertersTests.java | 33 +++++++ .../IndicesClientDocumentationIT.java | 78 ++++++++++++++++ .../high-level/indices/get_index.asciidoc | 88 +++++++++++++++++++ .../high-level/supported-apis.asciidoc | 2 + 7 files changed, 318 insertions(+) create mode 100644 docs/java-rest/high-level/indices/get_index.asciidoc diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java index 641480535c5ad..840130da40b14 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java @@ -39,6 +39,7 @@ import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest; import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse; import org.elasticsearch.action.admin.indices.get.GetIndexRequest; +import org.elasticsearch.action.admin.indices.get.GetIndexResponse; import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest; import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse; import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest; @@ -437,6 +438,34 @@ public void getSettingsAsync(GetSettingsRequest getSettingsRequest, RequestOptio GetSettingsResponse::fromXContent, listener, emptySet()); } + /** + * Retrieve information about one or more indexes + * See + * Indices Get Index API on elastic.co + * @param getIndexRequest the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @return the response + * @throws IOException in case there is a problem sending the request or parsing back the response + */ + public GetIndexResponse getIndex(GetIndexRequest getIndexRequest, RequestOptions options) throws IOException { + return restHighLevelClient.performRequestAndParseEntity(getIndexRequest, RequestConverters::getIndex, options, + GetIndexResponse::fromXContent, emptySet()); + } + + /** + * Retrieve information about one or more indexes + * See + * Indices Get Index API on elastic.co + * @param getIndexRequest the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @param listener the listener to be notified upon request completion + */ + public void getIndexAsync(GetIndexRequest getIndexRequest, RequestOptions options, + ActionListener listener) { + restHighLevelClient.performRequestAsyncAndParseEntity(getIndexRequest, RequestConverters::getIndex, options, + GetIndexResponse::fromXContent, listener, emptySet()); + } + /** * Force merge one or more indices using the Force Merge API. * See diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java index 26f0b5c647404..efc48d9057550 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java @@ -834,6 +834,22 @@ static Request getSettings(GetSettingsRequest getSettingsRequest) { return request; } + static Request getIndex(GetIndexRequest getIndexRequest) { + String[] indices = getIndexRequest.indices() == null ? Strings.EMPTY_ARRAY : getIndexRequest.indices(); + + String endpoint = endpoint(indices); + Request request = new Request(HttpGet.METHOD_NAME, endpoint); + + Params params = new Params(request); + params.withIndicesOptions(getIndexRequest.indicesOptions()); + params.withLocal(getIndexRequest.local()); + params.withIncludeDefaults(getIndexRequest.includeDefaults()); + params.withHuman(getIndexRequest.humanReadable()); + params.withMasterTimeout(getIndexRequest.masterNodeTimeout()); + + return request; + } + static Request indicesExist(GetIndexRequest getIndexRequest) { // this can be called with no indices as argument by transport client, not via REST though if (getIndexRequest.indices() == null || getIndexRequest.indices().length == 0) { diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java index 405653a3841eb..5a186c54d8817 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java @@ -45,6 +45,7 @@ import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest; import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse; import org.elasticsearch.action.admin.indices.get.GetIndexRequest; +import org.elasticsearch.action.admin.indices.get.GetIndexResponse; import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest; import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse; import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest; @@ -99,6 +100,7 @@ import java.util.Map; import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS; +import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_SHARDS; import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractRawValues; import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractValue; import static org.hamcrest.CoreMatchers.hasItem; @@ -112,6 +114,7 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.startsWith; +import static org.hamcrest.core.IsInstanceOf.instanceOf; public class IndicesClientIT extends ESRestHighLevelClientTestCase { @@ -326,6 +329,75 @@ public void testGetSettingsWithDefaultsFiltered() throws IOException { assertEquals(1, getSettingsResponse.getIndexToDefaultSettings().get("get_settings_index").size()); } + @SuppressWarnings("unchecked") + public void testGetIndex() throws IOException { + String indexName = "get_index_test"; + Settings basicSettings = Settings.builder() + .put(SETTING_NUMBER_OF_SHARDS, 1) + .put(SETTING_NUMBER_OF_REPLICAS, 0) + .build(); + String mappings = "\"type-1\":{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}"; + createIndex(indexName, basicSettings, mappings); + + GetIndexRequest getIndexRequest = new GetIndexRequest() + .indices(indexName).includeDefaults(false); + GetIndexResponse getIndexResponse = + execute(getIndexRequest, highLevelClient().indices()::getIndex, highLevelClient().indices()::getIndexAsync); + + // default settings should be null + assertNull(getIndexResponse.getSetting(indexName, "index.refresh_interval")); + assertEquals("1", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_SHARDS)); + assertEquals("0", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_REPLICAS)); + assertNotNull(getIndexResponse.getMappings().get(indexName)); + assertNotNull(getIndexResponse.getMappings().get(indexName).get("type-1")); + Object o = getIndexResponse.getMappings().get(indexName).get("type-1").getSourceAsMap().get("properties"); + assertThat(o, instanceOf(Map.class)); + //noinspection unchecked + assertThat(((Map) o).get("field-1"), instanceOf(Map.class)); + //noinspection unchecked + Map fieldMapping = (Map) ((Map) o).get("field-1"); + assertEquals("integer", fieldMapping.get("type")); + } + + @SuppressWarnings("unchecked") + public void testGetIndexWithDefaults() throws IOException { + String indexName = "get_index_test"; + Settings basicSettings = Settings.builder() + .put(SETTING_NUMBER_OF_SHARDS, 1) + .put(SETTING_NUMBER_OF_REPLICAS, 0) + .build(); + String mappings = "\"type-1\":{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}"; + createIndex(indexName, basicSettings, mappings); + + GetIndexRequest getIndexRequest = new GetIndexRequest() + .indices(indexName).includeDefaults(true); + GetIndexResponse getIndexResponse = + execute(getIndexRequest, highLevelClient().indices()::getIndex, highLevelClient().indices()::getIndexAsync); + + assertNotNull(getIndexResponse.getSetting(indexName, "index.refresh_interval")); + assertEquals(IndexSettings.DEFAULT_REFRESH_INTERVAL, + getIndexResponse.defaultSettings().get(indexName).getAsTime("index.refresh_interval", null)); + assertEquals("1", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_SHARDS)); + assertEquals("0", getIndexResponse.getSetting(indexName, SETTING_NUMBER_OF_REPLICAS)); + assertNotNull(getIndexResponse.getMappings().get(indexName)); + assertNotNull(getIndexResponse.getMappings().get(indexName).get("type-1")); + Object o = getIndexResponse.getMappings().get(indexName).get("type-1").getSourceAsMap().get("properties"); + assertThat(o, instanceOf(Map.class)); + assertThat(((Map) o).get("field-1"), instanceOf(Map.class)); + Map fieldMapping = (Map) ((Map) o).get("field-1"); + assertEquals("integer", fieldMapping.get("type")); + } + + public void testGetIndexNonExistentIndex() throws IOException { + String nonExistentIndex = "index_that_doesnt_exist"; + assertFalse(indexExists(nonExistentIndex)); + + GetIndexRequest getIndexRequest = new GetIndexRequest().indices(nonExistentIndex); + ElasticsearchException exception = expectThrows(ElasticsearchException.class, + () -> execute(getIndexRequest, highLevelClient().indices()::getIndex, highLevelClient().indices()::getIndexAsync)); + assertEquals(RestStatus.NOT_FOUND, exception.status()); + } + public void testPutMapping() throws IOException { // Add mappings to index String indexName = "mapping_index"; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java index aa3788af7494b..e2e025ea4763c 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java @@ -584,6 +584,39 @@ public void testGetSettings() throws IOException { assertThat(request.getEntity(), nullValue()); } + public void testGetIndex() throws IOException { + String[] indicesUnderTest = randomBoolean() ? null : randomIndicesNames(0, 5); + + GetIndexRequest getIndexRequest = new GetIndexRequest().indices(indicesUnderTest); + + Map expectedParams = new HashMap<>(); + setRandomMasterTimeout(getIndexRequest, expectedParams); + setRandomIndicesOptions(getIndexRequest::indicesOptions, getIndexRequest::indicesOptions, expectedParams); + setRandomLocal(getIndexRequest, expectedParams); + setRandomHumanReadable(getIndexRequest, expectedParams); + + if (randomBoolean()) { + // the request object will not have include_defaults present unless it is set to + // true + getIndexRequest.includeDefaults(randomBoolean()); + if (getIndexRequest.includeDefaults()) { + expectedParams.put("include_defaults", Boolean.toString(true)); + } + } + + StringJoiner endpoint = new StringJoiner("/", "/", ""); + if (indicesUnderTest != null && indicesUnderTest.length > 0) { + endpoint.add(String.join(",", indicesUnderTest)); + } + + Request request = RequestConverters.getIndex(getIndexRequest); + + assertThat(endpoint.toString(), equalTo(request.getEndpoint())); + assertThat(request.getParameters(), equalTo(expectedParams)); + assertThat(request.getMethod(), equalTo(HttpGet.METHOD_NAME)); + assertThat(request.getEntity(), nullValue()); + } + public void testDeleteIndexEmptyIndices() { String[] indices = randomBoolean() ? null : Strings.EMPTY_ARRAY; ActionRequestValidationException validationException = new DeleteIndexRequest(indices).validate(); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java index 964757db372ae..dfec3af32f56f 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java @@ -44,6 +44,7 @@ import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest; import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse; import org.elasticsearch.action.admin.indices.get.GetIndexRequest; +import org.elasticsearch.action.admin.indices.get.GetIndexResponse; import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest; import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse; import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest; @@ -89,12 +90,14 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.IndexSettings; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.rest.RestStatus; import java.io.IOException; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -1235,6 +1238,81 @@ public void onFailure(Exception e) { assertTrue(latch.await(30L, TimeUnit.SECONDS)); } + public void testGetIndex() throws Exception { + RestHighLevelClient client = highLevelClient(); + + { + Settings settings = Settings.builder().put("number_of_shards", 3).build(); + String mappings = "{\"properties\":{\"field-1\":{\"type\":\"integer\"}}}"; + CreateIndexResponse createIndexResponse = client.indices().create( + new CreateIndexRequest("index", settings).mapping("doc", mappings, XContentType.JSON), + RequestOptions.DEFAULT); + assertTrue(createIndexResponse.isAcknowledged()); + } + + // tag::get-index-request + GetIndexRequest request = new GetIndexRequest().indices("index"); // <1> + // end::get-index-request + + // tag::get-index-request-indicesOptions + request.indicesOptions(IndicesOptions.lenientExpandOpen()); // <1> + // end::get-index-request-indicesOptions + + // tag::get-index-request-includeDefaults + request.includeDefaults(true); // <1> + // end::get-index-request-includeDefaults + + // tag::get-index-execute + GetIndexResponse getIndexResponse = client.indices().getIndex(request, RequestOptions.DEFAULT); + // end::get-index-execute + + // tag::get-index-response + ImmutableOpenMap indexMappings = getIndexResponse.getMappings().get("index"); // <1> + Map indexTypeMappings = indexMappings.get("doc").getSourceAsMap(); // <2> + List indexAliases = getIndexResponse.getAliases().get("index"); // <3> + String numberOfShardsString = getIndexResponse.getSetting("index", "index.number_of_shards"); // <4> + Settings indexSettings = getIndexResponse.getSettings().get("index"); // <5> + Integer numberOfShards = indexSettings.getAsInt("index.number_of_shards", null); // <6> + TimeValue time = getIndexResponse.defaultSettings().get("index") + .getAsTime("index.refresh_interval", null); // <7> + // end::get-index-response + + assertEquals( + Collections.singletonMap("properties", + Collections.singletonMap("field-1", Collections.singletonMap("type", "integer"))), + indexTypeMappings + ); + assertTrue(indexAliases.isEmpty()); + assertEquals(IndexSettings.DEFAULT_REFRESH_INTERVAL, time); + assertEquals("3", numberOfShardsString); + assertEquals(Integer.valueOf(3), numberOfShards); + + // tag::get-index-execute-listener + ActionListener listener = + new ActionListener() { + @Override + public void onResponse(GetIndexResponse getIndexResponse) { + // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }; + // end::get-index-execute-listener + + // Replace the empty listener by a blocking listener in test + final CountDownLatch latch = new CountDownLatch(1); + listener = new LatchedActionListener<>(listener, latch); + + // tag::get-index-execute-async + client.indices().getIndexAsync(request, RequestOptions.DEFAULT, listener); // <1> + // end::get-index-execute-async + + assertTrue(latch.await(30L, TimeUnit.SECONDS)); + } + public void testForceMergeIndex() throws Exception { RestHighLevelClient client = highLevelClient(); diff --git a/docs/java-rest/high-level/indices/get_index.asciidoc b/docs/java-rest/high-level/indices/get_index.asciidoc new file mode 100644 index 0000000000000..5fb1599613ad3 --- /dev/null +++ b/docs/java-rest/high-level/indices/get_index.asciidoc @@ -0,0 +1,88 @@ +[[java-rest-high-get-index]] +=== Get Index API + +[[java-rest-high-get-index-request]] +==== Get Index Request + +A `GetIndexRequest` requires one or more `index` arguments: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-index-request] +-------------------------------------------------- +<1> The index whose information we want to retrieve + +==== Optional arguments +The following arguments can optionally be provided: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-index-request-includeDefaults] +-------------------------------------------------- +<1> If true, defaults will be returned for settings not explicitly set on the index + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-index-request-indicesOptions] +-------------------------------------------------- +<1> Setting `IndicesOptions` controls how unavailable indices are resolved and +how wildcard expressions are expanded + +[[java-rest-high-get-index-sync]] +==== Synchronous Execution + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-index-execute] +-------------------------------------------------- + +[[java-rest-high-get-index-async]] +==== Asynchronous Execution + +The asynchronous execution of a Get Index request requires both the `GetIndexRequest` +instance and an `ActionListener` instance to be passed to the asynchronous +method: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-index-execute-async] +-------------------------------------------------- +<1> The `GetIndexRequest` to execute and the `ActionListener` to use when +the execution completes + +The asynchronous method does not block and returns immediately. Once it is +completed the `ActionListener` is called back using the `onResponse` method +if the execution successfully completed or using the `onFailure` method if +it failed. + +A typical listener for `GetIndexResponse` looks like: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-index-execute-listener] +-------------------------------------------------- +<1> Called when the execution is successfully completed. The response is +provided as an argument. +<2> Called in case of failure. The raised exception is provided as an argument. + +[[java-rest-high-get-index-response]] +==== Get Index Response + +The returned `GetIndexResponse` allows to retrieve information about the +executed operation as follows: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-index-response] +-------------------------------------------------- +<1> Retrieve a Map of different types to `MappingMetadata` for `index`. +<2> Retrieve a Map for the properties for document type `doc`. +<3> Get the list of aliases for `index`. +<4> Get the value for the setting string `index.number_of_shards` for `index`. If the setting was not explicitly +specified but was part of the default settings (and includeDefault was `true`) then the default setting would be +retrieved. +<5> Retrieve all settings for `index`. +<6> The `Settings` objects gives more flexibility. Here it is used to extract the setting `index.number_of_shards` as an +integer. +<7> Get the default setting `index.refresh_interval` (if `includeDefault` was set to `true`). If `includeDefault` was set +to `false`, `getIndexResponse.defaultSettings()` will return an empty map. \ No newline at end of file diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index 0faf73e59074a..582dfa8b9c0e6 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -78,6 +78,7 @@ Index Management:: * <> * <> * <> +* <> Mapping Management:: * <> @@ -113,6 +114,7 @@ include::indices/get_settings.asciidoc[] include::indices/put_template.asciidoc[] include::indices/validate_query.asciidoc[] include::indices/get_templates.asciidoc[] +include::indices/get_index.asciidoc[] == Cluster APIs