Add UpdateRequest support to High Level Rest client (#23266)
This commit adds support for UpdateRequest to the High Level Rest client
This commit is contained in:
parent
eeaa0ccec2
commit
09734e7469
|
@ -32,12 +32,16 @@ import org.elasticsearch.action.get.GetRequest;
|
|||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.support.ActiveShardCount;
|
||||
import org.elasticsearch.action.support.WriteRequest;
|
||||
import org.elasticsearch.action.update.UpdateRequest;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.lucene.uid.Versions;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.VersionType;
|
||||
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
|
@ -118,6 +122,48 @@ final class Request {
|
|||
return new Request(method, endpoint, parameters.getParams(), entity);
|
||||
}
|
||||
|
||||
static Request update(UpdateRequest updateRequest) throws IOException {
|
||||
String endpoint = endpoint(updateRequest.index(), updateRequest.type(), updateRequest.id(), "_update");
|
||||
|
||||
Params parameters = Params.builder();
|
||||
parameters.withRouting(updateRequest.routing());
|
||||
parameters.withParent(updateRequest.parent());
|
||||
parameters.withTimeout(updateRequest.timeout());
|
||||
parameters.withRefreshPolicy(updateRequest.getRefreshPolicy());
|
||||
parameters.withWaitForActiveShards(updateRequest.waitForActiveShards());
|
||||
parameters.withDocAsUpsert(updateRequest.docAsUpsert());
|
||||
parameters.withFetchSourceContext(updateRequest.fetchSource());
|
||||
parameters.withRetryOnConflict(updateRequest.retryOnConflict());
|
||||
parameters.withVersion(updateRequest.version());
|
||||
parameters.withVersionType(updateRequest.versionType());
|
||||
|
||||
// The Java API allows update requests with different content types
|
||||
// set for the partial document and the upsert document. This client
|
||||
// only accepts update requests that have the same content types set
|
||||
// for both doc and upsert.
|
||||
XContentType xContentType = null;
|
||||
if (updateRequest.doc() != null) {
|
||||
xContentType = updateRequest.doc().getContentType();
|
||||
}
|
||||
if (updateRequest.upsertRequest() != null) {
|
||||
XContentType upsertContentType = updateRequest.upsertRequest().getContentType();
|
||||
if ((xContentType != null) && (xContentType != upsertContentType)) {
|
||||
throw new IllegalStateException("Update request cannot have different content types for doc [" + xContentType + "]" +
|
||||
" and upsert [" + upsertContentType + "] documents");
|
||||
} else {
|
||||
xContentType = upsertContentType;
|
||||
}
|
||||
}
|
||||
if (xContentType == null) {
|
||||
xContentType = Requests.INDEX_CONTENT_TYPE;
|
||||
}
|
||||
|
||||
BytesRef source = XContentHelper.toXContent(updateRequest, xContentType, false).toBytesRef();
|
||||
HttpEntity entity = new ByteArrayEntity(source.bytes, source.offset, source.length, ContentType.create(xContentType.mediaType()));
|
||||
|
||||
return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to build request's endpoint.
|
||||
*/
|
||||
|
@ -160,6 +206,13 @@ final class Request {
|
|||
return this;
|
||||
}
|
||||
|
||||
Params withDocAsUpsert(boolean docAsUpsert) {
|
||||
if (docAsUpsert) {
|
||||
return putParam("doc_as_upsert", Boolean.TRUE.toString());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Params withFetchSourceContext(FetchSourceContext fetchSourceContext) {
|
||||
if (fetchSourceContext != null) {
|
||||
if (fetchSourceContext.fetchSource() == false) {
|
||||
|
@ -203,7 +256,14 @@ final class Request {
|
|||
|
||||
Params withRefreshPolicy(WriteRequest.RefreshPolicy refreshPolicy) {
|
||||
if (refreshPolicy != WriteRequest.RefreshPolicy.NONE) {
|
||||
putParam("refresh", refreshPolicy.getValue());
|
||||
return putParam("refresh", refreshPolicy.getValue());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
Params withRetryOnConflict(int retryOnConflict) {
|
||||
if (retryOnConflict > 0) {
|
||||
return putParam("retry_on_conflict", String.valueOf(retryOnConflict));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ import org.elasticsearch.action.get.GetResponse;
|
|||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.action.main.MainRequest;
|
||||
import org.elasticsearch.action.update.UpdateRequest;
|
||||
import org.elasticsearch.action.update.UpdateResponse;
|
||||
import org.elasticsearch.common.CheckedFunction;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
@ -39,10 +41,8 @@ import org.elasticsearch.rest.BytesRestResponse;
|
|||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static java.util.Collections.singleton;
|
||||
|
@ -121,14 +121,35 @@ public class RestHighLevelClient {
|
|||
performRequestAsyncAndParseEntity(indexRequest, Request::index, IndexResponse::fromXContent, listener, emptySet(), headers);
|
||||
}
|
||||
|
||||
private <Req extends ActionRequest, Resp> Resp performRequestAndParseEntity(Req request, Function<Req, Request> requestConverter,
|
||||
CheckedFunction<XContentParser, Resp, IOException> entityParser, Set<Integer> ignores, Header... headers) throws IOException {
|
||||
/**
|
||||
* Updates a document using the Update API
|
||||
* <p>
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html">Update API on elastic.co</a>
|
||||
*/
|
||||
public UpdateResponse update(UpdateRequest updateRequest, Header... headers) throws IOException {
|
||||
return performRequestAndParseEntity(updateRequest, Request::update, UpdateResponse::fromXContent, emptySet(), headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously updates a document using the Update API
|
||||
* <p>
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html">Update API on elastic.co</a>
|
||||
*/
|
||||
public void updateAsync(UpdateRequest updateRequest, ActionListener<UpdateResponse> listener, Header... headers) {
|
||||
performRequestAsyncAndParseEntity(updateRequest, Request::update, UpdateResponse::fromXContent, listener, emptySet(), headers);
|
||||
}
|
||||
|
||||
private <Req extends ActionRequest, Resp> Resp performRequestAndParseEntity(Req request,
|
||||
CheckedFunction<Req, Request, IOException> requestConverter,
|
||||
CheckedFunction<XContentParser, Resp, IOException> entityParser,
|
||||
Set<Integer> ignores, Header... headers) throws IOException {
|
||||
return performRequest(request, requestConverter, (response) -> parseEntity(response.getEntity(), entityParser), ignores, headers);
|
||||
}
|
||||
|
||||
<Req extends ActionRequest, Resp> Resp performRequest(Req request, Function<Req, Request> requestConverter,
|
||||
CheckedFunction<Response, Resp, IOException> responseConverter, Set<Integer> ignores, Header... headers) throws IOException {
|
||||
|
||||
<Req extends ActionRequest, Resp> Resp performRequest(Req request,
|
||||
CheckedFunction<Req, Request, IOException> requestConverter,
|
||||
CheckedFunction<Response, Resp, IOException> responseConverter,
|
||||
Set<Integer> ignores, Header... headers) throws IOException {
|
||||
ActionRequestValidationException validationException = request.validate();
|
||||
if (validationException != null) {
|
||||
throw validationException;
|
||||
|
@ -154,22 +175,31 @@ public class RestHighLevelClient {
|
|||
}
|
||||
}
|
||||
|
||||
private <Req extends ActionRequest, Resp> void performRequestAsyncAndParseEntity(Req request, Function<Req, Request> requestConverter,
|
||||
CheckedFunction<XContentParser, Resp, IOException> entityParser, ActionListener<Resp> listener,
|
||||
Set<Integer> ignores, Header... headers) {
|
||||
private <Req extends ActionRequest, Resp> void performRequestAsyncAndParseEntity(Req request,
|
||||
CheckedFunction<Req, Request, IOException> requestConverter,
|
||||
CheckedFunction<XContentParser, Resp, IOException> entityParser,
|
||||
ActionListener<Resp> listener, Set<Integer> ignores, Header... headers) {
|
||||
performRequestAsync(request, requestConverter, (response) -> parseEntity(response.getEntity(), entityParser),
|
||||
listener, ignores, headers);
|
||||
}
|
||||
|
||||
<Req extends ActionRequest, Resp> void performRequestAsync(Req request, Function<Req, Request> requestConverter,
|
||||
CheckedFunction<Response, Resp, IOException> responseConverter, ActionListener<Resp> listener,
|
||||
Set<Integer> ignores, Header... headers) {
|
||||
<Req extends ActionRequest, Resp> void performRequestAsync(Req request,
|
||||
CheckedFunction<Req, Request, IOException> requestConverter,
|
||||
CheckedFunction<Response, Resp, IOException> responseConverter,
|
||||
ActionListener<Resp> listener, Set<Integer> ignores, Header... headers) {
|
||||
ActionRequestValidationException validationException = request.validate();
|
||||
if (validationException != null) {
|
||||
listener.onFailure(validationException);
|
||||
return;
|
||||
}
|
||||
Request req = requestConverter.apply(request);
|
||||
Request req;
|
||||
try {
|
||||
req = requestConverter.apply(request);
|
||||
} catch (Exception e) {
|
||||
listener.onFailure(e);
|
||||
return;
|
||||
}
|
||||
|
||||
ResponseListener responseListener = wrapResponseListener(responseConverter, listener, ignores);
|
||||
client.performRequestAsync(req.method, req.endpoint, req.params, req.entity, responseListener, headers);
|
||||
}
|
||||
|
|
|
@ -29,18 +29,23 @@ import org.elasticsearch.action.get.GetRequest;
|
|||
import org.elasticsearch.action.get.GetResponse;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.index.IndexResponse;
|
||||
import org.elasticsearch.action.update.UpdateRequest;
|
||||
import org.elasticsearch.action.update.UpdateResponse;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.VersionType;
|
||||
import org.elasticsearch.index.get.GetResult;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptType;
|
||||
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static java.util.Collections.singletonMap;
|
||||
|
||||
public class CrudIT extends ESRestHighLevelClientTestCase {
|
||||
|
||||
|
@ -262,4 +267,177 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
|
|||
"version conflict, document already exists (current version [1])]", exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testUpdate() throws IOException {
|
||||
{
|
||||
UpdateRequest updateRequest = new UpdateRequest("index", "type", "does_not_exist");
|
||||
updateRequest.doc(singletonMap("field", "value"), randomFrom(XContentType.values()));
|
||||
|
||||
ElasticsearchStatusException exception = expectThrows(ElasticsearchStatusException.class, () ->
|
||||
execute(updateRequest, highLevelClient()::update, highLevelClient()::updateAsync));
|
||||
assertEquals(RestStatus.NOT_FOUND, exception.status());
|
||||
assertEquals("Elasticsearch exception [type=document_missing_exception, reason=[type][does_not_exist]: document missing]",
|
||||
exception.getMessage());
|
||||
}
|
||||
{
|
||||
IndexRequest indexRequest = new IndexRequest("index", "type", "id");
|
||||
indexRequest.source(singletonMap("field", "value"));
|
||||
IndexResponse indexResponse = highLevelClient().index(indexRequest);
|
||||
assertEquals(RestStatus.CREATED, indexResponse.status());
|
||||
|
||||
UpdateRequest updateRequest = new UpdateRequest("index", "type", "id");
|
||||
updateRequest.doc(singletonMap("field", "updated"), randomFrom(XContentType.values()));
|
||||
|
||||
UpdateResponse updateResponse = execute(updateRequest, highLevelClient()::update, highLevelClient()::updateAsync);
|
||||
assertEquals(RestStatus.OK, updateResponse.status());
|
||||
assertEquals(indexResponse.getVersion() + 1, updateResponse.getVersion());
|
||||
|
||||
UpdateRequest updateRequestConflict = new UpdateRequest("index", "type", "id");
|
||||
updateRequestConflict.doc(singletonMap("field", "with_version_conflict"), randomFrom(XContentType.values()));
|
||||
updateRequestConflict.version(indexResponse.getVersion());
|
||||
|
||||
ElasticsearchStatusException exception = expectThrows(ElasticsearchStatusException.class, () ->
|
||||
execute(updateRequestConflict, highLevelClient()::update, highLevelClient()::updateAsync));
|
||||
assertEquals(RestStatus.CONFLICT, exception.status());
|
||||
assertEquals("Elasticsearch exception [type=version_conflict_engine_exception, reason=[type][id]: version conflict, " +
|
||||
"current version [2] is different than the one provided [1]]", exception.getMessage());
|
||||
}
|
||||
{
|
||||
ElasticsearchStatusException exception = expectThrows(ElasticsearchStatusException.class, () -> {
|
||||
UpdateRequest updateRequest = new UpdateRequest("index", "type", "id");
|
||||
updateRequest.doc(singletonMap("field", "updated"), randomFrom(XContentType.values()));
|
||||
if (randomBoolean()) {
|
||||
updateRequest.parent("missing");
|
||||
} else {
|
||||
updateRequest.routing("missing");
|
||||
}
|
||||
execute(updateRequest, highLevelClient()::update, highLevelClient()::updateAsync);
|
||||
});
|
||||
|
||||
assertEquals(RestStatus.NOT_FOUND, exception.status());
|
||||
assertEquals("Elasticsearch exception [type=document_missing_exception, reason=[type][id]: document missing]",
|
||||
exception.getMessage());
|
||||
}
|
||||
{
|
||||
IndexRequest indexRequest = new IndexRequest("index", "type", "with_script");
|
||||
indexRequest.source(singletonMap("counter", 12));
|
||||
IndexResponse indexResponse = highLevelClient().index(indexRequest);
|
||||
assertEquals(RestStatus.CREATED, indexResponse.status());
|
||||
|
||||
UpdateRequest updateRequest = new UpdateRequest("index", "type", "with_script");
|
||||
Script script = new Script(ScriptType.INLINE, "painless", "ctx._source.counter += params.count", singletonMap("count", 8));
|
||||
updateRequest.script(script);
|
||||
updateRequest.fetchSource(true);
|
||||
|
||||
UpdateResponse updateResponse = execute(updateRequest, highLevelClient()::update, highLevelClient()::updateAsync);
|
||||
assertEquals(RestStatus.OK, updateResponse.status());
|
||||
assertEquals(DocWriteResponse.Result.UPDATED, updateResponse.getResult());
|
||||
assertEquals(2L, updateResponse.getVersion());
|
||||
assertEquals(20, updateResponse.getGetResult().sourceAsMap().get("counter"));
|
||||
|
||||
}
|
||||
{
|
||||
IndexRequest indexRequest = new IndexRequest("index", "type", "with_doc");
|
||||
indexRequest.source("field_1", "one", "field_3", "three");
|
||||
indexRequest.version(12L);
|
||||
indexRequest.versionType(VersionType.EXTERNAL);
|
||||
IndexResponse indexResponse = highLevelClient().index(indexRequest);
|
||||
assertEquals(RestStatus.CREATED, indexResponse.status());
|
||||
assertEquals(12L, indexResponse.getVersion());
|
||||
|
||||
UpdateRequest updateRequest = new UpdateRequest("index", "type", "with_doc");
|
||||
updateRequest.doc(singletonMap("field_2", "two"), randomFrom(XContentType.values()));
|
||||
updateRequest.fetchSource("field_*", "field_3");
|
||||
|
||||
UpdateResponse updateResponse = execute(updateRequest, highLevelClient()::update, highLevelClient()::updateAsync);
|
||||
assertEquals(RestStatus.OK, updateResponse.status());
|
||||
assertEquals(DocWriteResponse.Result.UPDATED, updateResponse.getResult());
|
||||
assertEquals(13L, updateResponse.getVersion());
|
||||
GetResult getResult = updateResponse.getGetResult();
|
||||
assertEquals(13L, updateResponse.getVersion());
|
||||
Map<String, Object> sourceAsMap = getResult.sourceAsMap();
|
||||
assertEquals("one", sourceAsMap.get("field_1"));
|
||||
assertEquals("two", sourceAsMap.get("field_2"));
|
||||
assertFalse(sourceAsMap.containsKey("field_3"));
|
||||
}
|
||||
{
|
||||
IndexRequest indexRequest = new IndexRequest("index", "type", "noop");
|
||||
indexRequest.source("field", "value");
|
||||
IndexResponse indexResponse = highLevelClient().index(indexRequest);
|
||||
assertEquals(RestStatus.CREATED, indexResponse.status());
|
||||
assertEquals(1L, indexResponse.getVersion());
|
||||
|
||||
UpdateRequest updateRequest = new UpdateRequest("index", "type", "noop");
|
||||
updateRequest.doc(singletonMap("field", "value"), randomFrom(XContentType.values()));
|
||||
|
||||
UpdateResponse updateResponse = execute(updateRequest, highLevelClient()::update, highLevelClient()::updateAsync);
|
||||
assertEquals(RestStatus.OK, updateResponse.status());
|
||||
assertEquals(DocWriteResponse.Result.NOOP, updateResponse.getResult());
|
||||
assertEquals(1L, updateResponse.getVersion());
|
||||
|
||||
updateRequest.detectNoop(false);
|
||||
|
||||
updateResponse = execute(updateRequest, highLevelClient()::update, highLevelClient()::updateAsync);
|
||||
assertEquals(RestStatus.OK, updateResponse.status());
|
||||
assertEquals(DocWriteResponse.Result.UPDATED, updateResponse.getResult());
|
||||
assertEquals(2L, updateResponse.getVersion());
|
||||
}
|
||||
{
|
||||
UpdateRequest updateRequest = new UpdateRequest("index", "type", "with_upsert");
|
||||
updateRequest.upsert(singletonMap("doc_status", "created"));
|
||||
updateRequest.doc(singletonMap("doc_status", "updated"));
|
||||
updateRequest.fetchSource(true);
|
||||
|
||||
UpdateResponse updateResponse = execute(updateRequest, highLevelClient()::update, highLevelClient()::updateAsync);
|
||||
assertEquals(RestStatus.CREATED, updateResponse.status());
|
||||
assertEquals("index", updateResponse.getIndex());
|
||||
assertEquals("type", updateResponse.getType());
|
||||
assertEquals("with_upsert", updateResponse.getId());
|
||||
GetResult getResult = updateResponse.getGetResult();
|
||||
assertEquals(1L, updateResponse.getVersion());
|
||||
assertEquals("created", getResult.sourceAsMap().get("doc_status"));
|
||||
}
|
||||
{
|
||||
UpdateRequest updateRequest = new UpdateRequest("index", "type", "with_doc_as_upsert");
|
||||
updateRequest.doc(singletonMap("field", "initialized"));
|
||||
updateRequest.fetchSource(true);
|
||||
updateRequest.docAsUpsert(true);
|
||||
|
||||
UpdateResponse updateResponse = execute(updateRequest, highLevelClient()::update, highLevelClient()::updateAsync);
|
||||
assertEquals(RestStatus.CREATED, updateResponse.status());
|
||||
assertEquals("index", updateResponse.getIndex());
|
||||
assertEquals("type", updateResponse.getType());
|
||||
assertEquals("with_doc_as_upsert", updateResponse.getId());
|
||||
GetResult getResult = updateResponse.getGetResult();
|
||||
assertEquals(1L, updateResponse.getVersion());
|
||||
assertEquals("initialized", getResult.sourceAsMap().get("field"));
|
||||
}
|
||||
{
|
||||
UpdateRequest updateRequest = new UpdateRequest("index", "type", "with_scripted_upsert");
|
||||
updateRequest.fetchSource(true);
|
||||
updateRequest.script(new Script(ScriptType.INLINE, "painless", "ctx._source.level = params.test", singletonMap("test", "C")));
|
||||
updateRequest.scriptedUpsert(true);
|
||||
updateRequest.upsert(singletonMap("level", "A"));
|
||||
|
||||
UpdateResponse updateResponse = execute(updateRequest, highLevelClient()::update, highLevelClient()::updateAsync);
|
||||
assertEquals(RestStatus.CREATED, updateResponse.status());
|
||||
assertEquals("index", updateResponse.getIndex());
|
||||
assertEquals("type", updateResponse.getType());
|
||||
assertEquals("with_scripted_upsert", updateResponse.getId());
|
||||
|
||||
GetResult getResult = updateResponse.getGetResult();
|
||||
assertEquals(1L, updateResponse.getVersion());
|
||||
assertEquals("C", getResult.sourceAsMap().get("level"));
|
||||
}
|
||||
{
|
||||
IllegalStateException exception = expectThrows(IllegalStateException.class, () -> {
|
||||
UpdateRequest updateRequest = new UpdateRequest("index", "type", "id");
|
||||
updateRequest.doc(new IndexRequest().source(Collections.singletonMap("field", "doc"), XContentType.JSON));
|
||||
updateRequest.upsert(new IndexRequest().source(Collections.singletonMap("field", "upsert"), XContentType.YAML));
|
||||
execute(updateRequest, highLevelClient()::update, highLevelClient()::updateAsync);
|
||||
});
|
||||
assertEquals("Update request cannot have different content types for doc [JSON] and upsert [YAML] documents",
|
||||
exception.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,21 +26,29 @@ import org.elasticsearch.action.get.GetRequest;
|
|||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.support.WriteRequest;
|
||||
import org.elasticsearch.action.support.replication.ReplicationRequest;
|
||||
import org.elasticsearch.action.update.UpdateRequest;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.lucene.uid.Versions;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.VersionType;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.RandomObjects;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent;
|
||||
|
||||
public class RequestTests extends ESTestCase {
|
||||
|
||||
public void testPing() {
|
||||
|
@ -121,43 +129,7 @@ public class RequestTests extends ESTestCase {
|
|||
expectedParams.put("stored_fields", storedFieldsParam.toString());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
if (randomBoolean()) {
|
||||
boolean fetchSource = randomBoolean();
|
||||
getRequest.fetchSourceContext(new FetchSourceContext(fetchSource));
|
||||
if (fetchSource == false) {
|
||||
expectedParams.put("_source", "false");
|
||||
}
|
||||
} else {
|
||||
int numIncludes = randomIntBetween(0, 5);
|
||||
String[] includes = new String[numIncludes];
|
||||
StringBuilder includesParam = new StringBuilder();
|
||||
for (int i = 0; i < numIncludes; i++) {
|
||||
String include = randomAsciiOfLengthBetween(3, 10);
|
||||
includes[i] = include;
|
||||
includesParam.append(include);
|
||||
if (i < numIncludes - 1) {
|
||||
includesParam.append(",");
|
||||
}
|
||||
}
|
||||
if (numIncludes > 0) {
|
||||
expectedParams.put("_source_include", includesParam.toString());
|
||||
}
|
||||
int numExcludes = randomIntBetween(0, 5);
|
||||
String[] excludes = new String[numExcludes];
|
||||
StringBuilder excludesParam = new StringBuilder();
|
||||
for (int i = 0; i < numExcludes; i++) {
|
||||
String exclude = randomAsciiOfLengthBetween(3, 10);
|
||||
excludes[i] = exclude;
|
||||
excludesParam.append(exclude);
|
||||
if (i < numExcludes - 1) {
|
||||
excludesParam.append(",");
|
||||
}
|
||||
}
|
||||
if (numExcludes > 0) {
|
||||
expectedParams.put("_source_exclude", excludesParam.toString());
|
||||
}
|
||||
getRequest.fetchSourceContext(new FetchSourceContext(true, includes, excludes));
|
||||
}
|
||||
randomizeFetchSourceContextParams(getRequest::fetchSourceContext, expectedParams);
|
||||
}
|
||||
}
|
||||
Request request = requestConverter.apply(getRequest);
|
||||
|
@ -271,6 +243,132 @@ public class RequestTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testUpdate() throws IOException {
|
||||
XContentType xContentType = randomFrom(XContentType.values());
|
||||
|
||||
Map<String, String> expectedParams = new HashMap<>();
|
||||
String index = randomAsciiOfLengthBetween(3, 10);
|
||||
String type = randomAsciiOfLengthBetween(3, 10);
|
||||
String id = randomAsciiOfLengthBetween(3, 10);
|
||||
|
||||
UpdateRequest updateRequest = new UpdateRequest(index, type, id);
|
||||
updateRequest.detectNoop(randomBoolean());
|
||||
|
||||
if (randomBoolean()) {
|
||||
BytesReference source = RandomObjects.randomSource(random(), xContentType);
|
||||
updateRequest.doc(new IndexRequest().source(source, xContentType));
|
||||
|
||||
boolean docAsUpsert = randomBoolean();
|
||||
updateRequest.docAsUpsert(docAsUpsert);
|
||||
if (docAsUpsert) {
|
||||
expectedParams.put("doc_as_upsert", "true");
|
||||
}
|
||||
} else {
|
||||
updateRequest.script(new Script("_value + 1"));
|
||||
updateRequest.scriptedUpsert(randomBoolean());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
BytesReference source = RandomObjects.randomSource(random(), xContentType);
|
||||
updateRequest.upsert(new IndexRequest().source(source, xContentType));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
String routing = randomAsciiOfLengthBetween(3, 10);
|
||||
updateRequest.routing(routing);
|
||||
expectedParams.put("routing", routing);
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
String parent = randomAsciiOfLengthBetween(3, 10);
|
||||
updateRequest.parent(parent);
|
||||
expectedParams.put("parent", parent);
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
String timeout = randomTimeValue();
|
||||
updateRequest.timeout(timeout);
|
||||
expectedParams.put("timeout", timeout);
|
||||
} else {
|
||||
expectedParams.put("timeout", ReplicationRequest.DEFAULT_TIMEOUT.getStringRep());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
WriteRequest.RefreshPolicy refreshPolicy = randomFrom(WriteRequest.RefreshPolicy.values());
|
||||
updateRequest.setRefreshPolicy(refreshPolicy);
|
||||
if (refreshPolicy != WriteRequest.RefreshPolicy.NONE) {
|
||||
expectedParams.put("refresh", refreshPolicy.getValue());
|
||||
}
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
int waitForActiveShards = randomIntBetween(0, 10);
|
||||
updateRequest.waitForActiveShards(waitForActiveShards);
|
||||
expectedParams.put("wait_for_active_shards", String.valueOf(waitForActiveShards));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
long version = randomLong();
|
||||
updateRequest.version(version);
|
||||
if (version != Versions.MATCH_ANY) {
|
||||
expectedParams.put("version", Long.toString(version));
|
||||
}
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
VersionType versionType = randomFrom(VersionType.values());
|
||||
updateRequest.versionType(versionType);
|
||||
if (versionType != VersionType.INTERNAL) {
|
||||
expectedParams.put("version_type", versionType.name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
int retryOnConflict = randomIntBetween(0, 5);
|
||||
updateRequest.retryOnConflict(retryOnConflict);
|
||||
if (retryOnConflict > 0) {
|
||||
expectedParams.put("retry_on_conflict", String.valueOf(retryOnConflict));
|
||||
}
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
randomizeFetchSourceContextParams(updateRequest::fetchSource, expectedParams);
|
||||
}
|
||||
|
||||
Request request = Request.update(updateRequest);
|
||||
assertEquals("/" + index + "/" + type + "/" + id + "/_update", request.endpoint);
|
||||
assertEquals(expectedParams, request.params);
|
||||
assertEquals("POST", request.method);
|
||||
|
||||
HttpEntity entity = request.entity;
|
||||
assertNotNull(entity);
|
||||
assertTrue(entity instanceof ByteArrayEntity);
|
||||
|
||||
UpdateRequest parsedUpdateRequest = new UpdateRequest();
|
||||
|
||||
XContentType entityContentType = XContentType.fromMediaTypeOrFormat(entity.getContentType().getValue());
|
||||
try (XContentParser parser = createParser(entityContentType.xContent(), entity.getContent())) {
|
||||
parsedUpdateRequest.fromXContent(parser);
|
||||
}
|
||||
|
||||
assertEquals(updateRequest.scriptedUpsert(), parsedUpdateRequest.scriptedUpsert());
|
||||
assertEquals(updateRequest.docAsUpsert(), parsedUpdateRequest.docAsUpsert());
|
||||
assertEquals(updateRequest.detectNoop(), parsedUpdateRequest.detectNoop());
|
||||
assertEquals(updateRequest.fetchSource(), parsedUpdateRequest.fetchSource());
|
||||
assertEquals(updateRequest.script(), parsedUpdateRequest.script());
|
||||
if (updateRequest.doc() != null) {
|
||||
assertToXContentEquivalent(updateRequest.doc().source(), parsedUpdateRequest.doc().source(), xContentType);
|
||||
} else {
|
||||
assertNull(parsedUpdateRequest.doc());
|
||||
}
|
||||
if (updateRequest.upsertRequest() != null) {
|
||||
assertToXContentEquivalent(updateRequest.upsertRequest().source(), parsedUpdateRequest.upsertRequest().source(), xContentType);
|
||||
} else {
|
||||
assertNull(parsedUpdateRequest.upsertRequest());
|
||||
}
|
||||
}
|
||||
|
||||
public void testUpdateWithDifferentContentTypes() throws IOException {
|
||||
IllegalStateException exception = expectThrows(IllegalStateException.class, () -> {
|
||||
UpdateRequest updateRequest = new UpdateRequest();
|
||||
updateRequest.doc(new IndexRequest().source(Collections.singletonMap("field", "doc"), XContentType.JSON));
|
||||
updateRequest.upsert(new IndexRequest().source(Collections.singletonMap("field", "upsert"), XContentType.YAML));
|
||||
Request.update(updateRequest);
|
||||
});
|
||||
assertEquals("Update request cannot have different content types for doc [JSON] and upsert [YAML] documents",
|
||||
exception.getMessage());
|
||||
}
|
||||
|
||||
public void testParams() {
|
||||
final int nbParams = randomIntBetween(0, 10);
|
||||
Request.Params params = Request.Params.builder();
|
||||
|
@ -307,4 +405,49 @@ public class RequestTests extends ESTestCase {
|
|||
assertEquals("/a/b/_create", Request.endpoint("a", "b", "_create"));
|
||||
assertEquals("/a/b/c/_create", Request.endpoint("a", "b", "c", "_create"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Randomize the {@link FetchSourceContext} request parameters.
|
||||
*/
|
||||
private static void randomizeFetchSourceContextParams(Consumer<FetchSourceContext> consumer, Map<String, String> expectedParams) {
|
||||
if (randomBoolean()) {
|
||||
if (randomBoolean()) {
|
||||
boolean fetchSource = randomBoolean();
|
||||
consumer.accept(new FetchSourceContext(fetchSource));
|
||||
if (fetchSource == false) {
|
||||
expectedParams.put("_source", "false");
|
||||
}
|
||||
} else {
|
||||
int numIncludes = randomIntBetween(0, 5);
|
||||
String[] includes = new String[numIncludes];
|
||||
StringBuilder includesParam = new StringBuilder();
|
||||
for (int i = 0; i < numIncludes; i++) {
|
||||
String include = randomAsciiOfLengthBetween(3, 10);
|
||||
includes[i] = include;
|
||||
includesParam.append(include);
|
||||
if (i < numIncludes - 1) {
|
||||
includesParam.append(",");
|
||||
}
|
||||
}
|
||||
if (numIncludes > 0) {
|
||||
expectedParams.put("_source_include", includesParam.toString());
|
||||
}
|
||||
int numExcludes = randomIntBetween(0, 5);
|
||||
String[] excludes = new String[numExcludes];
|
||||
StringBuilder excludesParam = new StringBuilder();
|
||||
for (int i = 0; i < numExcludes; i++) {
|
||||
String exclude = randomAsciiOfLengthBetween(3, 10);
|
||||
excludes[i] = exclude;
|
||||
excludesParam.append(exclude);
|
||||
if (i < numExcludes - 1) {
|
||||
excludesParam.append(",");
|
||||
}
|
||||
}
|
||||
if (numExcludes > 0) {
|
||||
expectedParams.put("_source_exclude", excludesParam.toString());
|
||||
}
|
||||
consumer.accept(new FetchSourceContext(true, includes, excludes));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -239,7 +239,8 @@ public class RestHighLevelClientTests extends ESTestCase {
|
|||
|
||||
public void testPerformRequestOnSuccess() throws IOException {
|
||||
MainRequest mainRequest = new MainRequest();
|
||||
Function<MainRequest, Request> requestConverter = request -> new Request("GET", "/", Collections.emptyMap(), null);
|
||||
CheckedFunction<MainRequest, Request, IOException> requestConverter = request ->
|
||||
new Request("GET", "/", Collections.emptyMap(), null);
|
||||
RestStatus restStatus = randomFrom(RestStatus.values());
|
||||
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
|
||||
Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
|
||||
|
@ -260,7 +261,8 @@ public class RestHighLevelClientTests extends ESTestCase {
|
|||
|
||||
public void testPerformRequestOnResponseExceptionWithoutEntity() throws IOException {
|
||||
MainRequest mainRequest = new MainRequest();
|
||||
Function<MainRequest, Request> requestConverter = request -> new Request("GET", "/", Collections.emptyMap(), null);
|
||||
CheckedFunction<MainRequest, Request, IOException> requestConverter = request ->
|
||||
new Request("GET", "/", Collections.emptyMap(), null);
|
||||
RestStatus restStatus = randomFrom(RestStatus.values());
|
||||
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
|
||||
Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
|
||||
|
@ -277,7 +279,8 @@ public class RestHighLevelClientTests extends ESTestCase {
|
|||
|
||||
public void testPerformRequestOnResponseExceptionWithEntity() throws IOException {
|
||||
MainRequest mainRequest = new MainRequest();
|
||||
Function<MainRequest, Request> requestConverter = request -> new Request("GET", "/", Collections.emptyMap(), null);
|
||||
CheckedFunction<MainRequest, Request, IOException> requestConverter = request ->
|
||||
new Request("GET", "/", Collections.emptyMap(), null);
|
||||
RestStatus restStatus = randomFrom(RestStatus.values());
|
||||
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
|
||||
httpResponse.setEntity(new StringEntity("{\"error\":\"test error message\",\"status\":" + restStatus.getStatus() + "}",
|
||||
|
@ -296,7 +299,8 @@ public class RestHighLevelClientTests extends ESTestCase {
|
|||
|
||||
public void testPerformRequestOnResponseExceptionWithBrokenEntity() throws IOException {
|
||||
MainRequest mainRequest = new MainRequest();
|
||||
Function<MainRequest, Request> requestConverter = request -> new Request("GET", "/", Collections.emptyMap(), null);
|
||||
CheckedFunction<MainRequest, Request, IOException> requestConverter = request ->
|
||||
new Request("GET", "/", Collections.emptyMap(), null);
|
||||
RestStatus restStatus = randomFrom(RestStatus.values());
|
||||
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
|
||||
httpResponse.setEntity(new StringEntity("{\"error\":", ContentType.APPLICATION_JSON));
|
||||
|
@ -315,7 +319,8 @@ public class RestHighLevelClientTests extends ESTestCase {
|
|||
|
||||
public void testPerformRequestOnResponseExceptionWithBrokenEntity2() throws IOException {
|
||||
MainRequest mainRequest = new MainRequest();
|
||||
Function<MainRequest, Request> requestConverter = request -> new Request("GET", "/", Collections.emptyMap(), null);
|
||||
CheckedFunction<MainRequest, Request, IOException> requestConverter = request ->
|
||||
new Request("GET", "/", Collections.emptyMap(), null);
|
||||
RestStatus restStatus = randomFrom(RestStatus.values());
|
||||
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
|
||||
httpResponse.setEntity(new StringEntity("{\"status\":" + restStatus.getStatus() + "}", ContentType.APPLICATION_JSON));
|
||||
|
@ -334,7 +339,8 @@ public class RestHighLevelClientTests extends ESTestCase {
|
|||
|
||||
public void testPerformRequestOnResponseExceptionWithIgnores() throws IOException {
|
||||
MainRequest mainRequest = new MainRequest();
|
||||
Function<MainRequest, Request> requestConverter = request -> new Request("GET", "/", Collections.emptyMap(), null);
|
||||
CheckedFunction<MainRequest, Request, IOException> requestConverter = request ->
|
||||
new Request("GET", "/", Collections.emptyMap(), null);
|
||||
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(RestStatus.NOT_FOUND));
|
||||
Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
|
||||
ResponseException responseException = new ResponseException(mockResponse);
|
||||
|
@ -347,7 +353,8 @@ public class RestHighLevelClientTests extends ESTestCase {
|
|||
|
||||
public void testPerformRequestOnResponseExceptionWithIgnoresErrorNoBody() throws IOException {
|
||||
MainRequest mainRequest = new MainRequest();
|
||||
Function<MainRequest, Request> requestConverter = request -> new Request("GET", "/", Collections.emptyMap(), null);
|
||||
CheckedFunction<MainRequest, Request, IOException> requestConverter = request ->
|
||||
new Request("GET", "/", Collections.emptyMap(), null);
|
||||
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(RestStatus.NOT_FOUND));
|
||||
Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
|
||||
ResponseException responseException = new ResponseException(mockResponse);
|
||||
|
@ -363,7 +370,8 @@ public class RestHighLevelClientTests extends ESTestCase {
|
|||
|
||||
public void testPerformRequestOnResponseExceptionWithIgnoresErrorValidBody() throws IOException {
|
||||
MainRequest mainRequest = new MainRequest();
|
||||
Function<MainRequest, Request> requestConverter = request -> new Request("GET", "/", Collections.emptyMap(), null);
|
||||
CheckedFunction<MainRequest, Request, IOException> requestConverter = request ->
|
||||
new Request("GET", "/", Collections.emptyMap(), null);
|
||||
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(RestStatus.NOT_FOUND));
|
||||
httpResponse.setEntity(new StringEntity("{\"error\":\"test error message\",\"status\":404}",
|
||||
ContentType.APPLICATION_JSON));
|
||||
|
|
Loading…
Reference in New Issue