From 0a8d8d7ae389b2d19137fc7ea83c0d2ddb366a1b Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Thu, 23 Jan 2020 13:16:20 +0100 Subject: [PATCH] Add Get Source API to the HLRC (#51342) Backport to 7.x branch of #50885. Relates to #47678 Co-authored-by: Maxim --- .../client/RequestConverters.java | 27 +++- .../client/RestHighLevelClient.java | 30 +++++ .../client/core/GetSourceRequest.java | 126 ++++++++++++++++++ .../client/core/GetSourceResponse.java | 47 +++++++ .../java/org/elasticsearch/client/CrudIT.java | 68 ++++++++++ .../client/RequestConvertersTests.java | 43 ++++++ .../client/RestHighLevelClientTests.java | 1 - .../client/core/GetSourceResponseTests.java | 73 ++++++++++ .../documentation/CRUDDocumentationIT.java | 99 ++++++++++++++ .../high-level/document/get-source.asciidoc | 72 ++++++++++ .../high-level/supported-apis.asciidoc | 2 + 11 files changed, 582 insertions(+), 6 deletions(-) create mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceRequest.java create mode 100644 client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceResponse.java create mode 100644 client/rest-high-level/src/test/java/org/elasticsearch/client/core/GetSourceResponseTests.java create mode 100644 docs/java-rest/high-level/document/get-source.asciidoc 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 06ef48bf4ff..59f9b3e1aba 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 @@ -49,6 +49,7 @@ import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.client.core.CountRequest; +import org.elasticsearch.client.core.GetSourceRequest; import org.elasticsearch.client.core.MultiTermVectorsRequest; import org.elasticsearch.client.core.TermVectorsRequest; import org.elasticsearch.client.indices.AnalyzeRequest; @@ -281,6 +282,14 @@ final class RequestConverters { } static Request sourceExists(GetRequest getRequest) { + Params parameters = new Params(); + parameters.withPreference(getRequest.preference()); + parameters.withRouting(getRequest.routing()); + parameters.withRefresh(getRequest.refresh()); + parameters.withRealtime(getRequest.realtime()); + parameters.withFetchSourceContext(getRequest.fetchSourceContext()); + // Version params are not currently supported by the _source API so are not passed + String optionalType = getRequest.type(); String endpoint; if (optionalType.equals(MapperService.SINGLE_MAPPING_NAME)) { @@ -289,12 +298,20 @@ final class RequestConverters { endpoint = endpoint(getRequest.index(), optionalType, getRequest.id(), "_source"); } Request request = new Request(HttpHead.METHOD_NAME, endpoint); + request.addParameters(parameters.asMap()); + return request; + } + + static Request getSource(GetSourceRequest getSourceRequest) { Params parameters = new Params(); - parameters.withPreference(getRequest.preference()); - parameters.withRouting(getRequest.routing()); - parameters.withRefresh(getRequest.refresh()); - parameters.withRealtime(getRequest.realtime()); - // Version params are not currently supported by the source exists API so are not passed + parameters.withPreference(getSourceRequest.preference()); + parameters.withRouting(getSourceRequest.routing()); + parameters.withRefresh(getSourceRequest.refresh()); + parameters.withRealtime(getSourceRequest.realtime()); + parameters.withFetchSourceContext(getSourceRequest.fetchSourceContext()); + + String endpoint = endpoint(getSourceRequest.index(), "_source", getSourceRequest.id()); + Request request = new Request(HttpGet.METHOD_NAME, endpoint); request.addParameters(parameters.asMap()); return request; } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java index 3986d4e8f13..d5c745414b4 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java @@ -56,6 +56,8 @@ import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.client.core.CountRequest; import org.elasticsearch.client.core.CountResponse; +import org.elasticsearch.client.core.GetSourceRequest; +import org.elasticsearch.client.core.GetSourceResponse; import org.elasticsearch.client.core.MainRequest; import org.elasticsearch.client.core.MainResponse; import org.elasticsearch.client.core.MultiTermVectorsRequest; @@ -860,6 +862,34 @@ public class RestHighLevelClient implements Closeable { RestHighLevelClient::convertExistsResponse, listener, emptySet()); } + /** + * Retrieves the source field only of a document using GetSource API. + * See Get Source API + * on elastic.co + * @param getRequest the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @return the response + */ + public GetSourceResponse getSource(GetSourceRequest getRequest, RequestOptions options) throws IOException { + return performRequestAndParseEntity(getRequest, RequestConverters::getSource, options, + GetSourceResponse::fromXContent, emptySet()); + } + + /** + * Asynchronously retrieves the source field only of a document using GetSource API. + * See Get Source API + * on elastic.co + * @param getRequest 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 + * @return cancellable that may be used to cancel the request + */ + public final Cancellable getSourceAsync(GetSourceRequest getRequest, RequestOptions options, + ActionListener listener) { + return performRequestAsyncAndParseEntity(getRequest, RequestConverters::getSource, options, + GetSourceResponse::fromXContent, listener, emptySet()); + } + /** * Index a document using the Index API. * See Index API on elastic.co diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceRequest.java new file mode 100644 index 00000000000..791c36cd94e --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceRequest.java @@ -0,0 +1,126 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.client.core; + +import org.elasticsearch.client.Validatable; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.search.fetch.subphase.FetchSourceContext; + +import java.io.IOException; + +public final class GetSourceRequest implements Validatable, ToXContentObject { + private String routing; + private String preference; + + private boolean refresh = false; + private boolean realtime = true; + + private FetchSourceContext fetchSourceContext; + + private String index; + private String id; + + public GetSourceRequest(String index, String id) { + this.index = index; + this.id = id; + } + + /** + * Controls the shard routing of the request. Using this value to hash the shard + * and not the id. + */ + public GetSourceRequest routing(String routing) { + if (routing != null && routing.length() == 0) { + this.routing = null; + } else { + this.routing = routing; + } + return this; + } + + /** + * Sets the preference to execute the search. Defaults to randomize across shards. Can be set to + * {@code _local} to prefer local shards or a custom value, which guarantees that the same order + * will be used across different requests. + */ + public GetSourceRequest preference(String preference) { + this.preference = preference; + return this; + } + + /** + * Should a refresh be executed before this get operation causing the operation to + * return the latest value. Note, heavy get should not set this to {@code true}. Defaults + * to {@code false}. + */ + public GetSourceRequest refresh(boolean refresh) { + this.refresh = refresh; + return this; + } + + public GetSourceRequest realtime(boolean realtime) { + this.realtime = realtime; + return this; + } + + /** + * Allows setting the {@link FetchSourceContext} for this request, controlling if and how _source should be returned. + * Note, the {@code fetchSource} field of the context must be set to {@code true}. + */ + + public GetSourceRequest fetchSourceContext(FetchSourceContext context) { + this.fetchSourceContext = context; + return this; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return null; + } + + public String index() { + return index; + } + + public String id() { + return id; + } + + public String routing() { + return routing; + } + + public String preference() { + return preference; + } + + public boolean refresh() { + return refresh; + } + + public boolean realtime() { + return realtime; + } + + public FetchSourceContext fetchSourceContext() { + return fetchSourceContext; + } +} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceResponse.java new file mode 100644 index 00000000000..02d29e3eb45 --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/GetSourceResponse.java @@ -0,0 +1,47 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.client.core; + +import org.elasticsearch.common.xcontent.XContentParser; + +import java.io.IOException; +import java.util.Map; + +public final class GetSourceResponse { + + private final Map source; + + public GetSourceResponse(Map source) { + this.source = source; + } + + public static GetSourceResponse fromXContent(XContentParser parser) throws IOException { + return new GetSourceResponse(parser.map()); + } + + public Map getSource() { + return this.source; + } + + @Override + public String toString() { + return source.toString(); + } +} diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/CrudIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/CrudIT.java index c828a73e17d..3a5e2f3b092 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/CrudIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/CrudIT.java @@ -38,6 +38,8 @@ import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.support.WriteRequest.RefreshPolicy; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; +import org.elasticsearch.client.core.GetSourceRequest; +import org.elasticsearch.client.core.GetSourceResponse; import org.elasticsearch.client.core.MultiTermVectorsRequest; import org.elasticsearch.client.core.MultiTermVectorsResponse; import org.elasticsearch.client.core.TermVectorsRequest; @@ -70,6 +72,7 @@ import org.joda.time.format.DateTimeFormat; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; @@ -456,6 +459,71 @@ public class CrudIT extends ESRestHighLevelClientTestCase { assertEquals("id2", secondResponse.getId()); } + public void testGetSource() throws IOException { + { + GetSourceRequest getRequest = new GetSourceRequest("index", "id"); + ElasticsearchException exception = expectThrows(ElasticsearchException.class, + () -> execute(getRequest, highLevelClient()::getSource, highLevelClient()::getSourceAsync)); + assertEquals(RestStatus.NOT_FOUND, exception.status()); + assertEquals("Elasticsearch exception [type=index_not_found_exception, reason=no such index [index]]", exception.getMessage()); + assertEquals("index", exception.getMetadata("es.index").get(0)); + } + IndexRequest index = new IndexRequest("index").id("id"); + String document = "{\"field1\":\"value1\",\"field2\":\"value2\"}"; + index.source(document, XContentType.JSON); + index.setRefreshPolicy(RefreshPolicy.IMMEDIATE); + highLevelClient().index(index, RequestOptions.DEFAULT); + { + GetSourceRequest getRequest = new GetSourceRequest("index", "id"); + GetSourceResponse response = execute(getRequest, highLevelClient()::getSource, highLevelClient()::getSourceAsync); + Map expectedResponse = new HashMap<>(); + expectedResponse.put("field1", "value1"); + expectedResponse.put("field2", "value2"); + assertEquals(expectedResponse, response.getSource()); + } + { + GetSourceRequest getRequest = new GetSourceRequest("index", "does_not_exist"); + ElasticsearchException exception = expectThrows(ElasticsearchException.class, + () -> execute(getRequest, highLevelClient()::getSource, highLevelClient()::getSourceAsync)); + assertEquals(RestStatus.NOT_FOUND, exception.status()); + assertEquals("Elasticsearch exception [type=resource_not_found_exception, " + + "reason=Document not found [index]/[_doc]/[does_not_exist]]", exception.getMessage()); + } + { + GetSourceRequest getRequest = new GetSourceRequest("index", "id"); + getRequest.fetchSourceContext(new FetchSourceContext(true, Strings.EMPTY_ARRAY, Strings.EMPTY_ARRAY)); + GetSourceResponse response = execute(getRequest, highLevelClient()::getSource, highLevelClient()::getSourceAsync); + Map expectedResponse = new HashMap<>(); + expectedResponse.put("field1", "value1"); + expectedResponse.put("field2", "value2"); + assertEquals(expectedResponse, response.getSource()); + } + { + GetSourceRequest getRequest = new GetSourceRequest("index", "id"); + getRequest.fetchSourceContext(new FetchSourceContext(true, new String[]{"field1"}, Strings.EMPTY_ARRAY)); + GetSourceResponse response = execute(getRequest, highLevelClient()::getSource, highLevelClient()::getSourceAsync); + Map expectedResponse = new HashMap<>(); + expectedResponse.put("field1", "value1"); + assertEquals(expectedResponse, response.getSource()); + } + { + GetSourceRequest getRequest = new GetSourceRequest("index", "id"); + getRequest.fetchSourceContext(new FetchSourceContext(true, Strings.EMPTY_ARRAY, new String[]{"field1"})); + GetSourceResponse response = execute(getRequest, highLevelClient()::getSource, highLevelClient()::getSourceAsync); + Map expectedResponse = new HashMap<>(); + expectedResponse.put("field2", "value2"); + assertEquals(expectedResponse, response.getSource()); + } + { + GetSourceRequest getRequest = new GetSourceRequest("index", "id"); + getRequest.fetchSourceContext(new FetchSourceContext(false)); + ElasticsearchException exception = expectThrows(ElasticsearchException.class, + () -> execute(getRequest, highLevelClient()::getSource, highLevelClient()::getSourceAsync)); + assertEquals("Elasticsearch exception [type=action_request_validation_exception, " + + "reason=Validation Failed: 1: fetching source can not be disabled;]", exception.getMessage()); + } + } + public void testIndex() throws IOException { final XContentType xContentType = randomFrom(XContentType.values()); { 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 f02e62eefcf..ac80636a3d6 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 @@ -54,6 +54,7 @@ import org.elasticsearch.action.support.replication.ReplicationRequest; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.client.RequestConverters.EndpointBuilder; import org.elasticsearch.client.core.CountRequest; +import org.elasticsearch.client.core.GetSourceRequest; import org.elasticsearch.client.core.MultiTermVectorsRequest; import org.elasticsearch.client.core.TermVectorsRequest; import org.elasticsearch.client.indices.AnalyzeRequest; @@ -172,6 +173,10 @@ public class RequestConvertersTests extends ESTestCase { doTestSourceExists((index, id) -> new GetRequest(index, type, id)); } + public void testGetSource() throws IOException { + doTestGetSource((index, id) -> new GetSourceRequest(index, id)); + } + private static void doTestSourceExists(BiFunction requestFunction) throws IOException { String index = randomAlphaOfLengthBetween(3, 10); String id = randomAlphaOfLengthBetween(3, 10); @@ -215,6 +220,44 @@ public class RequestConvertersTests extends ESTestCase { assertNull(request.getEntity()); } + private static void doTestGetSource(BiFunction requestFunction) throws IOException { + String index = randomAlphaOfLengthBetween(3, 10); + String id = randomAlphaOfLengthBetween(3, 10); + final GetSourceRequest getRequest = requestFunction.apply(index, id); + + Map expectedParams = new HashMap<>(); + if (randomBoolean()) { + String preference = randomAlphaOfLengthBetween(3, 10); + getRequest.preference(preference); + expectedParams.put("preference", preference); + } + if (randomBoolean()) { + String routing = randomAlphaOfLengthBetween(3, 10); + getRequest.routing(routing); + expectedParams.put("routing", routing); + } + if (randomBoolean()) { + boolean realtime = randomBoolean(); + getRequest.realtime(realtime); + if (realtime == false) { + expectedParams.put("realtime", "false"); + } + } + if (randomBoolean()) { + boolean refresh = randomBoolean(); + getRequest.refresh(refresh); + if (refresh) { + expectedParams.put("refresh", "true"); + } + } + Request request = RequestConverters.getSource(getRequest); + assertEquals(HttpGet.METHOD_NAME, request.getMethod()); + assertEquals("/" + index + "/_source/" + id, request.getEndpoint()); + + assertEquals(expectedParams, request.getParameters()); + assertNull(request.getEntity()); + } + public void testMultiGet() throws IOException { Map expectedParams = new HashMap<>(); MultiGetRequest multiGetRequest = new MultiGetRequest(); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java index 317c98ea0d9..da0eb7eebe1 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java @@ -777,7 +777,6 @@ public class RestHighLevelClientTests extends ESTestCase { "create", "get_script_context", "get_script_languages", - "get_source", "indices.exists_type", "indices.get_upgrade", "indices.put_alias", diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/core/GetSourceResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/core/GetSourceResponseTests.java new file mode 100644 index 00000000000..0d4422712f4 --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/core/GetSourceResponseTests.java @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.client.core; + +import org.elasticsearch.client.AbstractResponseTestCase; +import org.elasticsearch.common.bytes.BytesArray; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; + +import static org.hamcrest.CoreMatchers.equalTo; + +public final class GetSourceResponseTests extends + AbstractResponseTestCase { + + static class SourceOnlyResponse implements ToXContentObject { + + private final BytesReference source; + + SourceOnlyResponse(BytesReference source) { + this.source = source; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + // this implementation copied from RestGetSourceAction.RestGetSourceResponseListener::buildResponse + try (InputStream stream = source.streamInput()) { + builder.rawValue(stream, XContentHelper.xContentType(source)); + } + return builder; + } + } + + @Override + protected SourceOnlyResponse createServerTestInstance(XContentType xContentType) { + BytesReference source = new BytesArray("{\"field\":\"value\"}"); + return new SourceOnlyResponse(source); + } + + @Override + protected GetSourceResponse doParseToClientInstance(XContentParser parser) throws IOException { + return GetSourceResponse.fromXContent(parser); + } + + @Override + protected void assertInstances(SourceOnlyResponse serverTestInstance, GetSourceResponse clientInstance) { + assertThat(clientInstance.getSource(), equalTo(Collections.singletonMap("field", "value"))); + } +} diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CRUDDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CRUDDocumentationIT.java index 3ee230ddbdf..9d1f7f3cff5 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CRUDDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CRUDDocumentationIT.java @@ -53,6 +53,8 @@ import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.Response; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.RethrottleRequest; +import org.elasticsearch.client.core.GetSourceRequest; +import org.elasticsearch.client.core.GetSourceResponse; import org.elasticsearch.client.core.MultiTermVectorsRequest; import org.elasticsearch.client.core.MultiTermVectorsResponse; import org.elasticsearch.client.core.TermVectorsRequest; @@ -1398,6 +1400,103 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase { } } + public void testGetSource() throws Exception { + RestHighLevelClient client = highLevelClient(); + { + Request createIndex = new Request("PUT", "/posts"); + createIndex.setJsonEntity( + "{\n" + + " \"mappings\" : {\n" + + " \"properties\" : {\n" + + " \"message\" : {\n" + + " \"type\": \"text\",\n" + + " \"store\": true\n" + + " }\n" + + " }\n" + + " }\n" + + "}"); + Response response = client().performRequest(createIndex); + assertEquals(200, response.getStatusLine().getStatusCode()); + + IndexRequest indexRequest = new IndexRequest("posts").id("1") + .source("user", "kimchy", + "postDate", new Date(), + "message", "trying out Elasticsearch"); + IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT); + assertEquals(DocWriteResponse.Result.CREATED, indexResponse.getResult()); + } + + // tag::get-source-request + GetSourceRequest getSourceRequest = new GetSourceRequest( + "posts", // <1> + "1"); // <2> + // end::get-source-request + + //tag::get-source-request-optional + String[] includes = Strings.EMPTY_ARRAY; // <2> + String[] excludes = new String[]{"postDate"}; + getSourceRequest.fetchSourceContext( + new FetchSourceContext(true, includes, excludes)); // <1> + // end::get-source-request-optional + + //tag::get-source-request-routing + getSourceRequest.routing("routing"); // <1> + //end::get-source-request-routing + //tag::get-source-request-preference + getSourceRequest.preference("preference"); // <1> + //end::get-source-request-preference + //tag::get-source-request-realtime + getSourceRequest.realtime(false); // <1> + //end::get-source-request-realtime + //tag::get-source-request-refresh + getSourceRequest.refresh(true); // <1> + //end::get-source-request-refresh + + { + // tag::get-source-execute + GetSourceResponse response = + client.getSource(getSourceRequest, RequestOptions.DEFAULT); + // end::get-source-execute + // tag::get-source-response + Map source = response.getSource(); + // end::get-source-response + + Map expectSource = new HashMap<>(); + expectSource.put("user", "kimchy"); + expectSource.put("message", "trying out Elasticsearch"); + assertEquals(expectSource, source); + } + { + GetSourceRequest request = new GetSourceRequest("posts", "1"); + + // tag::get-source-execute-listener + ActionListener listener = + new ActionListener() { + @Override + public void onResponse(GetSourceResponse getResponse) { + // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }; + // end::get-source-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-source-execute-async + client.getSourceAsync(request, RequestOptions.DEFAULT, listener); // <1> + //end::get-source-execute-async + + assertTrue(latch.await(30L, TimeUnit.SECONDS)); + } + + } + public void testExists() throws Exception { RestHighLevelClient client = highLevelClient(); // tag::exists-request diff --git a/docs/java-rest/high-level/document/get-source.asciidoc b/docs/java-rest/high-level/document/get-source.asciidoc new file mode 100644 index 00000000000..f5a2ca8ec5d --- /dev/null +++ b/docs/java-rest/high-level/document/get-source.asciidoc @@ -0,0 +1,72 @@ +-- +:api: get-source +:request: GetSourceRequest +:response: GetSourceResponse +-- + +[id="{upid}-{api}"] +=== Get Source API + +This API helps to get only the `_source` field of a document. + +[id="{upid}-{api}-request"] +==== Get Source Request + +A +{request}+ requires the following arguments: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[{api}-request] +-------------------------------------------------- +<1> Index +<2> Document id + +[id="{upid}-{api}-request-optional"] +==== Optional arguments +The following arguments can optionally be provided: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[{api}-request-optional] +-------------------------------------------------- +<1> `FetchSourceContext` 's first argument `fetchSource` must be `true`, otherwise +`ElasticsearchException` get thrown +<2> Arguments of the context `excludes` and `includes` are optional +(see examples in Get API documentation) + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[{api}-request-routing] +-------------------------------------------------- +<1> Routing value + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[{api}-request-preference] +-------------------------------------------------- +<1> Preference value + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[{api}-request-realtime] +-------------------------------------------------- +<1> Set realtime flag to `false` (`true` by default) + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[{api}-request-refresh] +-------------------------------------------------- +<1> Perform a refresh before retrieving the document (`false` by default) + +include::../execution.asciidoc[] + +[id="{upid}-{api}-response"] +==== Get Source Response + +The returned +{response}+ contains the field `source` that represents the +source of a document as a map. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[{api}-response] +-------------------------------------------------- diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index 4b848819702..0204ba99a5a 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -11,6 +11,7 @@ The Java High Level REST Client supports the following Document APIs: Single document APIs:: * <<{upid}-index>> * <<{upid}-get>> +* <<{upid}-get-source>> * <<{upid}-exists>> * <<{upid}-delete>> * <<{upid}-update>> @@ -28,6 +29,7 @@ Multi-document APIs:: include::document/index.asciidoc[] include::document/get.asciidoc[] +include::document/get-source.asciidoc[] include::document/exists.asciidoc[] include::document/delete.asciidoc[] include::document/update.asciidoc[]