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 5e4559a8a4a..98d6736f786 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 @@ -30,6 +30,7 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; +import org.elasticsearch.action.admin.indices.get.GetIndexRequest; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; @@ -38,6 +39,7 @@ import org.elasticsearch.action.admin.indices.shrink.ResizeRequest; import org.elasticsearch.action.admin.indices.shrink.ResizeResponse; import java.io.IOException; +import java.util.Collections; import static java.util.Collections.emptySet; @@ -211,6 +213,39 @@ public final class IndicesClient { listener, emptySet(), headers); } + /** + * Checks if the index (indices) exists or not. + *

+ * See + * Indices Exists API on elastic.co + */ + public boolean exists(GetIndexRequest request, Header... headers) throws IOException { + return restHighLevelClient.performRequest( + request, + Request::indicesExist, + RestHighLevelClient::convertExistsResponse, + Collections.emptySet(), + headers + ); + } + + /** + * Asynchronously checks if the index (indices) exists or not. + *

+ * See + * Indices Exists API on elastic.co + */ + public void existsAsync(GetIndexRequest request, ActionListener listener, Header... headers) { + restHighLevelClient.performRequestAsync( + request, + Request::indicesExist, + RestHighLevelClient::convertExistsResponse, + listener, + Collections.emptySet(), + headers + ); + } + /** * Shrinks an index using the Shrink Index API *

diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java index 9c67a255e80..3061c67cd5c 100755 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java @@ -34,6 +34,7 @@ import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; +import org.elasticsearch.action.admin.indices.get.GetIndexRequest; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.shrink.ResizeRequest; @@ -582,6 +583,17 @@ public final class Request { return ContentType.create(xContentType.mediaTypeWithoutParameters(), (Charset) null); } + static Request indicesExist(GetIndexRequest request) { + String endpoint = endpoint(request.indices(), Strings.EMPTY_ARRAY, ""); + Params params = Params.builder(); + params.withLocal(request.local()); + params.withHuman(request.humanReadable()); + params.withIndicesOptions(request.indicesOptions()); + params.withFlatSettings(request.flatSettings()); + params.withIncludeDefaults(request.includeDefaults()); + return new Request(HttpHead.METHOD_NAME, endpoint, params.getParams(), null); + } + /** * Utility class to build request's parameters map and centralize all parameter names. */ @@ -729,8 +741,31 @@ public final class Request { return this; } + Params withHuman(boolean human) { + if (human) { + putParam("human", Boolean.toString(human)); + } + return this; + } + Params withLocal(boolean local) { - putParam("local", Boolean.toString(local)); + if (local) { + putParam("local", Boolean.toString(local)); + } + return this; + } + + Params withFlatSettings(boolean flatSettings) { + if (flatSettings) { + return putParam("flat_settings", Boolean.TRUE.toString()); + } + return this; + } + + Params withIncludeDefaults(boolean includeDefaults) { + if (includeDefaults) { + return putParam("include_defaults", Boolean.TRUE.toString()); + } return this; } 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 f9717f262b8..5baef93c0de 100755 --- 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 @@ -34,6 +34,7 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; +import org.elasticsearch.action.admin.indices.get.GetIndexRequest; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; @@ -58,6 +59,58 @@ import static org.hamcrest.Matchers.not; public class IndicesClientIT extends ESRestHighLevelClientTestCase { + public void testIndicesExists() throws IOException { + // Index present + { + String indexName = "test_index_exists_index_present"; + createIndex(indexName, Settings.EMPTY); + + GetIndexRequest request = new GetIndexRequest(); + request.indices(indexName); + + boolean response = execute( + request, + highLevelClient().indices()::exists, + highLevelClient().indices()::existsAsync + ); + assertTrue(response); + } + + // Index doesn't exist + { + String indexName = "non_existent_index"; + + GetIndexRequest request = new GetIndexRequest(); + request.indices(indexName); + + boolean response = execute( + request, + highLevelClient().indices()::exists, + highLevelClient().indices()::existsAsync + ); + assertFalse(response); + } + + // One index exists, one doesn't + { + String existingIndex = "apples"; + createIndex(existingIndex, Settings.EMPTY); + + String nonExistentIndex = "oranges"; + + GetIndexRequest request = new GetIndexRequest(); + request.indices(existingIndex, nonExistentIndex); + + boolean response = execute( + request, + highLevelClient().indices()::exists, + highLevelClient().indices()::existsAsync + ); + assertFalse(response); + } + + } + @SuppressWarnings({"unchecked", "rawtypes"}) public void testCreateIndex() throws IOException { { diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java index 0e6ae3b21d5..3e4add16707 100755 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java @@ -36,6 +36,7 @@ import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; +import org.elasticsearch.action.admin.indices.get.GetIndexRequest; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.shrink.ResizeRequest; @@ -55,6 +56,7 @@ import org.elasticsearch.action.support.ActiveShardCount; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.action.support.master.AcknowledgedRequest; +import org.elasticsearch.action.support.master.MasterNodeReadRequest; import org.elasticsearch.action.support.master.MasterNodeRequest; import org.elasticsearch.action.support.replication.ReplicationRequest; import org.elasticsearch.action.update.UpdateRequest; @@ -262,6 +264,26 @@ public class RequestTests extends ESTestCase { getAndExistsTest(Request::exists, HttpHead.METHOD_NAME); } + public void testIndicesExist() { + String[] indices = randomIndicesNames(1, 10); + + GetIndexRequest getIndexRequest = new GetIndexRequest().indices(indices); + + Map expectedParams = new HashMap<>(); + setRandomIndicesOptions(getIndexRequest::indicesOptions, getIndexRequest::indicesOptions, expectedParams); + setRandomLocal(getIndexRequest, expectedParams); + setRandomFlatSettings(getIndexRequest, expectedParams); + setRandomHumanReadable(getIndexRequest, expectedParams); + setRandomIncludeDefaults(getIndexRequest, expectedParams); + + final Request request = Request.indicesExist(getIndexRequest); + + assertEquals(HttpHead.METHOD_NAME, request.getMethod()); + assertEquals("/" + String.join(",", indices), request.getEndpoint()); + assertThat(expectedParams, equalTo(request.getParameters())); + assertNull(request.getEntity()); + } + private static void getAndExistsTest(Function requestConverter, String method) { String index = randomAlphaOfLengthBetween(3, 10); String type = randomAlphaOfLengthBetween(3, 10); @@ -1008,12 +1030,7 @@ public class RequestTests extends ESTestCase { String[] aliases = randomIndicesNames(indices.length == 0 ? 1 : 0, 5); getAliasesRequest.aliases(aliases); Map expectedParams = new HashMap<>(); - if (randomBoolean()) { - boolean local = randomBoolean(); - getAliasesRequest.local(local); - } - expectedParams.put("local", Boolean.toString(getAliasesRequest.local())); - + setRandomLocal(getAliasesRequest, expectedParams); setRandomIndicesOptions(getAliasesRequest::indicesOptions, getAliasesRequest::indicesOptions, expectedParams); Request request = Request.existsAlias(getAliasesRequest); @@ -1252,6 +1269,46 @@ public class RequestTests extends ESTestCase { } } + private static void setRandomIncludeDefaults(GetIndexRequest request, Map expectedParams) { + if (randomBoolean()) { + boolean includeDefaults = randomBoolean(); + request.includeDefaults(includeDefaults); + if (includeDefaults) { + expectedParams.put("include_defaults", String.valueOf(includeDefaults)); + } + } + } + + private static void setRandomHumanReadable(GetIndexRequest request, Map expectedParams) { + if (randomBoolean()) { + boolean humanReadable = randomBoolean(); + request.humanReadable(humanReadable); + if (humanReadable) { + expectedParams.put("human", String.valueOf(humanReadable)); + } + } + } + + private static void setRandomFlatSettings(GetIndexRequest request, Map expectedParams) { + if (randomBoolean()) { + boolean flatSettings = randomBoolean(); + request.flatSettings(flatSettings); + if (flatSettings) { + expectedParams.put("flat_settings", String.valueOf(flatSettings)); + } + } + } + + private static void setRandomLocal(MasterNodeReadRequest request, Map expectedParams) { + if (randomBoolean()) { + boolean local = randomBoolean(); + request.local(local); + if (local) { + expectedParams.put("local", String.valueOf(local)); + } + } + } + private static void setRandomTimeout(Consumer setter, TimeValue defaultTimeout, Map expectedParams) { if (randomBoolean()) { String timeout = randomTimeValue(); 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 13fb5097151..f4650bcf98e 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 @@ -19,6 +19,7 @@ package org.elasticsearch.client.documentation; +import org.apache.http.Header; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.LatchedActionListener; @@ -33,6 +34,7 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; +import org.elasticsearch.action.admin.indices.get.GetIndexRequest; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; @@ -74,6 +76,69 @@ import java.util.concurrent.TimeUnit; */ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase { + public void testIndicesExist() throws IOException { + RestHighLevelClient client = highLevelClient(); + + { + CreateIndexResponse createIndexResponse = client.indices().create(new CreateIndexRequest("twitter")); + assertTrue(createIndexResponse.isAcknowledged()); + } + + { + // tag::indices-exists-request + GetIndexRequest request = new GetIndexRequest(); + request.indices("twitter"); // <1> + // end::indices-exists-request + + IndicesOptions indicesOptions = IndicesOptions.strictExpand(); + // tag::indices-exists-request-optionals + request.local(false); // <1> + request.humanReadable(true); // <2> + request.includeDefaults(false); // <3> + request.flatSettings(false); // <4> + request.indicesOptions(indicesOptions); // <5> + // end::indices-exists-request-optionals + + Header[] headers = new Header[0]; + // tag::indices-exists-response + boolean exists = client.indices().exists(request, headers); + // end::indices-exists-response + assertTrue(exists); + } + } + + public void testIndicesExistAsync() throws IOException { + RestHighLevelClient client = highLevelClient(); + + { + CreateIndexResponse createIndexResponse = client.indices().create(new CreateIndexRequest("twitter")); + assertTrue(createIndexResponse.isAcknowledged()); + } + + { + GetIndexRequest request = new GetIndexRequest(); + request.indices("twitter"); + Header[] headers = new Header[0]; + + // tag::indices-exists-async + client.indices().existsAsync( + request, + new ActionListener() { + @Override + public void onResponse(Boolean exists) { + // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }, + headers + ); + // end::indices-exists-async + } + } public void testDeleteIndex() throws IOException { RestHighLevelClient client = highLevelClient(); diff --git a/docs/java-rest/high-level/apis/index.asciidoc b/docs/java-rest/high-level/apis/index.asciidoc index c7ae114bfde..8128de65bae 100644 --- a/docs/java-rest/high-level/apis/index.asciidoc +++ b/docs/java-rest/high-level/apis/index.asciidoc @@ -1,5 +1,7 @@ include::create_index.asciidoc[] +include::indices_exists.asciidoc[] + include::delete_index.asciidoc[] include::open_index.asciidoc[] diff --git a/docs/java-rest/high-level/apis/indices_exists.asciidoc b/docs/java-rest/high-level/apis/indices_exists.asciidoc new file mode 100644 index 00000000000..e5ae47ea17e --- /dev/null +++ b/docs/java-rest/high-level/apis/indices_exists.asciidoc @@ -0,0 +1,57 @@ +[[java-rest-high-indices-exists]] +=== Indices Exists API + +[[java-rest-high-indices-exists-request]] +==== Indices Exists Request + +The high-level REST client uses a `GetIndexRequest` for Indices Exists API. The index name (or indices' names) are required. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[indices-exists-request] +-------------------------------------------------- +<1> Index + +[[java-rest-high-indices-exists-optional-args]] +==== Optional arguments +Indices Exists API also accepts following optional arguments, through a `GetIndexRequest`: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[indices-exists-request-optionals] +-------------------------------------------------- +<1> Whether to return local information or retrieve the state from master node +<2> Return result in a format suitable for humans +<3> Whether to return all default setting for each of the indices +<4> Return settings in flat format +<5> Controls how unavailable indices are resolved and how wildcard expressions are expanded + +[[java-rest-high-indices-sync]] +==== Synchronous Execution +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[indices-exists-response] +-------------------------------------------------- + +[[java-rest-high-indices-async]] +==== Asynchronous Execution +As is the case with many other APIs, the Indices Exists API has an asynchronous variant in the +Java High Level REST Client. +The asynchronous variant returns void and accept an extra `ActionListener` as an argument. +The provided listener will be notified upon request completion or failure. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[indices-exists-async] +-------------------------------------------------- +<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-indices-exists-response]] +==== Response +The response is a `boolean` value, indicating whether the index (or indices) exist: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[indices-exists-response] +-------------------------------------------------- diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index a75d5f8c7ab..c77a063003c 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -6,6 +6,7 @@ The Java High Level REST Client supports the following APIs: Indices APIs:: * <> * <> +* <> * <> * <> * <> diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/exists/indices/IndicesExistsResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/exists/indices/IndicesExistsResponse.java index 82d98285e1e..fb2d5c0fa9b 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/exists/indices/IndicesExistsResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/exists/indices/IndicesExistsResponse.java @@ -51,4 +51,4 @@ public class IndicesExistsResponse extends ActionResponse { super.writeTo(out); out.writeBoolean(exists); } -} \ No newline at end of file +} diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexRequest.java b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexRequest.java index 0177799c8fd..43beba5b670 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexRequest.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexRequest.java @@ -33,7 +33,6 @@ import java.util.List; * A request to delete an index. Best created with {@link org.elasticsearch.client.Requests#deleteIndexRequest(String)}. */ public class GetIndexRequest extends ClusterInfoRequest { - public enum Feature { ALIASES((byte) 0, "_aliases", "_alias"), MAPPINGS((byte) 1, "_mappings", "_mapping"), @@ -99,6 +98,8 @@ public class GetIndexRequest extends ClusterInfoRequest { private static final Feature[] DEFAULT_FEATURES = new Feature[] { Feature.ALIASES, Feature.MAPPINGS, Feature.SETTINGS }; private Feature[] features = DEFAULT_FEATURES; private boolean humanReadable = false; + private transient boolean flatSettings = false; + private transient boolean includeDefaults = false; public GetIndexRequest() { @@ -149,6 +150,43 @@ public class GetIndexRequest extends ClusterInfoRequest { return humanReadable; } + /** + * Sets the value of "flat_settings". + * @param flatSettings value of "flat_settings" flag to be set + * @return this request + */ + public GetIndexRequest flatSettings(boolean flatSettings) { + this.flatSettings = flatSettings; + return this; + } + + /** + * Return settings in flat format. + * @return true if settings need to be returned in flat format; false otherwise. + */ + public boolean flatSettings() { + return flatSettings; + } + + /** + * Sets the value of "include_defaults". + * @param includeDefaults value of "include_defaults" to be set. + * @return this request + */ + public GetIndexRequest includeDefaults(boolean includeDefaults) { + this.includeDefaults = includeDefaults; + return this; + } + + /** + * Whether to return all default settings for each of the indices. + * @return true if defaults settings for each of the indices need to returned; + * false otherwise. + */ + public boolean includeDefaults() { + return includeDefaults; + } + @Override public void readFrom(StreamInput in) throws IOException { throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable"); diff --git a/server/src/main/java/org/elasticsearch/action/support/master/MasterNodeReadRequest.java b/server/src/main/java/org/elasticsearch/action/support/master/MasterNodeReadRequest.java index 92578d7f33f..3045bef46b8 100644 --- a/server/src/main/java/org/elasticsearch/action/support/master/MasterNodeReadRequest.java +++ b/server/src/main/java/org/elasticsearch/action/support/master/MasterNodeReadRequest.java @@ -51,6 +51,11 @@ public abstract class MasterNodeReadRequesttrue if local information is to be returned; + * false if information is to be retrieved from master node (default). + */ public final boolean local() { return local; }