From 232b219d9cf74d67e01629e9078138d22b116789 Mon Sep 17 00:00:00 2001 From: Catalin Ursachi Date: Mon, 18 Dec 2017 17:18:45 +0000 Subject: [PATCH 1/7] Added Put Mapping API to high-level Rest client (#27205) --- .../elasticsearch/client/IndicesClient.java | 25 +++++ .../org/elasticsearch/client/Request.java | 17 ++++ .../elasticsearch/client/IndicesClientIT.java | 34 +++++++ .../elasticsearch/client/RequestTests.java | 42 ++++++++ .../mapping/put/PutMappingRequest.java | 13 ++- .../mapping/put/PutMappingResponse.java | 25 ++++- .../create/CreateIndexRequestTests.java | 2 +- .../mapping/put/PutMappingRequestTests.java | 96 +++++++++++++++++++ .../mapping/put/PutMappingResponseTests.java | 85 ++++++++++++++++ 9 files changed, 336 insertions(+), 3 deletions(-) create mode 100644 core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java 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 57dafbba50994..5d673fe10cc03 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 @@ -25,6 +25,8 @@ 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.mapping.put.PutMappingRequest; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexResponse; @@ -89,6 +91,29 @@ public void createIndexAsync(CreateIndexRequest createIndexRequest, ActionListen listener, Collections.emptySet(), headers); } + /** + * Creates an index using the Put Mapping API + *

+ * See + * Put Mapping API on elastic.co + */ + public PutMappingResponse putMapping(PutMappingRequest putMappingRequest, Header... headers) throws IOException { + return restHighLevelClient.performRequestAndParseEntity(putMappingRequest, Request::putMapping, PutMappingResponse::fromXContent, + Collections.emptySet(), headers); + } + + /** + * Asynchronously creates an index using the Put Mapping API + *

+ * See + * Put Mapping API on elastic.co + */ + public void putMappingAsync(PutMappingRequest putMappingRequest, ActionListener listener, + Header... headers) { + restHighLevelClient.performRequestAsyncAndParseEntity(putMappingRequest, Request::putMapping, PutMappingResponse::fromXContent, + listener, Collections.emptySet(), headers); + } + /** * Opens an index using the Open 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 dd08179cf6297..6c99472ca25ed 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 @@ -31,6 +31,7 @@ import org.elasticsearch.action.DocWriteRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.delete.DeleteRequest; @@ -165,6 +166,18 @@ static Request createIndex(CreateIndexRequest createIndexRequest) throws IOExcep return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity); } + static Request putMapping(PutMappingRequest putMappingRequest) throws IOException { + String endpoint = endpoint(putMappingRequest.indices(), "_mapping", putMappingRequest.type()); + + Params parameters = Params.builder(); + parameters.withTimeout(putMappingRequest.timeout()); + parameters.withMasterTimeout(putMappingRequest.masterNodeTimeout()); + parameters.withUpdateAllTypes(putMappingRequest.updateAllTypes()); + + HttpEntity entity = createEntity(putMappingRequest, REQUEST_BODY_CONTENT_TYPE); + return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity); + } + static Request info() { return new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null); } @@ -432,6 +445,10 @@ static String endpoint(String[] indices, String[] types, String endpoint) { return endpoint(String.join(",", indices), String.join(",", types), endpoint); } + static String endpoint(String[] indices, String endpoint, String type) { + return endpoint(String.join(",", indices), endpoint, type); + } + /** * Utility method to build request's endpoint. */ 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 5f356c4c29f5e..8b2e1b7d48462 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 @@ -25,6 +25,8 @@ 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.mapping.put.PutMappingRequest; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexResponse; import org.elasticsearch.action.support.IndicesOptions; @@ -109,6 +111,38 @@ public void testCreateIndex() throws IOException { } } + @SuppressWarnings("unchecked") + public void testPutMapping() throws IOException { + { + // Add mappings to index + String indexName = "mapping_index"; + createIndex(indexName); + + PutMappingRequest putMappingRequest = new PutMappingRequest(indexName); + + putMappingRequest.type("type_name"); + + XContentBuilder mappingBuilder = JsonXContent.contentBuilder(); + mappingBuilder.startObject().startObject("properties").startObject("field"); + mappingBuilder.field("type", "text"); + mappingBuilder.endObject().endObject().endObject(); + putMappingRequest.source(mappingBuilder); + + PutMappingResponse putMappingResponse = + execute(putMappingRequest, highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync); + assertTrue(putMappingResponse.isAcknowledged()); + + Map indexMetaData = getIndexMetadata(indexName); + + Map mappingsData = (Map) indexMetaData.get("mappings"); + Map typeData = (Map) mappingsData.get("type_name"); + Map properties = (Map) typeData.get("properties"); + Map field = (Map) properties.get("field"); + + assertEquals("text", field.get("type")); + } + } + public void testDeleteIndex() throws IOException { { // Delete index if exists 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 019162bae37a7..148be2d7347a0 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 @@ -27,6 +27,7 @@ import org.elasticsearch.action.DocWriteRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkShardRequest; @@ -270,6 +271,47 @@ public void testCreateIndex() throws IOException { assertToXContentBody(createIndexRequest, request.getEntity()); } + public void testPutMapping() throws IOException { + PutMappingRequest putMappingRequest = new PutMappingRequest(); + + int numIndices = randomIntBetween(0, 5); + String[] indices = new String[numIndices]; + for (int i = 0; i < numIndices; i++) { + indices[i] = "index-" + randomAlphaOfLengthBetween(2, 5); + } + putMappingRequest.indices(indices); + + String type = randomAlphaOfLengthBetween(3, 10); + putMappingRequest.type(type); + + Map expectedParams = new HashMap<>(); + + setRandomTimeout(putMappingRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams); + setRandomMasterTimeout(putMappingRequest, expectedParams); + + if (randomBoolean()) { + boolean updateAllTypes = randomBoolean(); + putMappingRequest.updateAllTypes(updateAllTypes); + if (updateAllTypes) { + expectedParams.put("update_all_types", Boolean.TRUE.toString()); + } + } + + Request request = Request.putMapping(putMappingRequest); + StringJoiner endpoint = new StringJoiner("/", "/", ""); + String index = String.join(",", indices); + if (Strings.hasLength(index)) { + endpoint.add(index); + } + endpoint.add("_mapping"); + endpoint.add(type); + assertEquals(endpoint.toString(), request.getEndpoint()); + + assertEquals(expectedParams, request.getParameters()); + assertEquals("PUT", request.getMethod()); + assertToXContentBody(putMappingRequest, request.getEntity()); + } + public void testDeleteIndex() { DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(); diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequest.java b/core/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequest.java index eecbbc453ee4d..01a61cab7854e 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequest.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequest.java @@ -32,6 +32,7 @@ import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentHelper; @@ -57,7 +58,7 @@ * @see org.elasticsearch.client.IndicesAdminClient#putMapping(PutMappingRequest) * @see PutMappingResponse */ -public class PutMappingRequest extends AcknowledgedRequest implements IndicesRequest.Replaceable { +public class PutMappingRequest extends AcknowledgedRequest implements IndicesRequest.Replaceable, ToXContentObject { private static ObjectHashSet RESERVED_FIELDS = ObjectHashSet.from( "_uid", "_id", "_type", "_source", "_all", "_analyzer", "_parent", "_routing", "_index", @@ -326,4 +327,14 @@ public void writeTo(StreamOutput out) throws IOException { out.writeBoolean(updateAllTypes); out.writeOptionalWriteable(concreteIndex); } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + if (source != null) { + builder.rawValue(new BytesArray(source), XContentType.JSON); + } else { + builder.startObject().endObject(); + } + return builder; + } } diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponse.java b/core/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponse.java index 64b3c77f05067..f427a316c2e81 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponse.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponse.java @@ -22,13 +22,24 @@ import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; import java.io.IOException; /** * The response of put mapping operation. */ -public class PutMappingResponse extends AcknowledgedResponse { +public class PutMappingResponse extends AcknowledgedResponse implements ToXContentObject { + + private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("put_mapping", + true, args -> new PutMappingResponse((boolean) args[0])); + + static { + declareAcknowledgedField(PARSER); + } protected PutMappingResponse() { @@ -49,4 +60,16 @@ public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); writeAcknowledged(out); } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + addAcknowledgedField(builder); + builder.endObject(); + return builder; + } + + public static PutMappingResponse fromXContent(XContentParser parser) throws IOException { + return PARSER.apply(parser, null); + } } diff --git a/core/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java b/core/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java index 41691f70c06f3..633034b58a602 100644 --- a/core/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java +++ b/core/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java @@ -115,7 +115,7 @@ public void testToAndFromXContent() throws IOException { final XContentType xContentType = randomFrom(XContentType.values()); BytesReference originalBytes = toShuffledXContent(createIndexRequest, xContentType, EMPTY_PARAMS, humanReadable); - CreateIndexRequest parsedCreateIndexRequest = new CreateIndexRequest(createIndexRequest.index()); + CreateIndexRequest parsedCreateIndexRequest = new CreateIndexRequest(); parsedCreateIndexRequest.source(originalBytes, xContentType); assertMappingsEqual(createIndexRequest.mappings(), parsedCreateIndexRequest.mappings()); diff --git a/core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java b/core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java index 96dcef700a956..93c9b707df415 100644 --- a/core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java +++ b/core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java @@ -21,17 +21,25 @@ import org.elasticsearch.Version; import org.elasticsearch.action.ActionRequestValidationException; +import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesArray; +import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.common.xcontent.yaml.YamlXContent; import org.elasticsearch.index.Index; import org.elasticsearch.test.ESTestCase; import java.io.IOException; +import static org.elasticsearch.common.xcontent.ToXContent.EMPTY_PARAMS; + public class PutMappingRequestTests extends ESTestCase { public void testValidation() { @@ -94,4 +102,92 @@ public void testPutMappingRequestSerialization() throws IOException { } } } + + public void testToXContent() throws IOException { + PutMappingRequest request = new PutMappingRequest("foo"); + + request.type("my_type"); + + XContentBuilder mapping = JsonXContent.contentBuilder().startObject(); + mapping.startObject("properties"); + mapping.startObject("email"); + mapping.field("type", "text"); + mapping.endObject(); + mapping.endObject(); + mapping.endObject(); + request.source(mapping); + + String actualRequestBody = Strings.toString(request); + + String expectedRequestBody = "{\"properties\":{\"email\":{\"type\":\"text\"}}}"; + + assertEquals(expectedRequestBody, actualRequestBody); + } + + public void testToAndFromXContent() throws IOException { + + final PutMappingRequest putMappingRequest = createTestItem(); + + boolean humanReadable = randomBoolean(); + final XContentType xContentType = randomFrom(XContentType.values()); + BytesReference originalBytes = toShuffledXContent(putMappingRequest, xContentType, EMPTY_PARAMS, humanReadable); + + PutMappingRequest parsedPutMappingRequest = new PutMappingRequest(); + parsedPutMappingRequest.source(originalBytes, xContentType); + + assertMappingsEqual(putMappingRequest.source(), parsedPutMappingRequest.source()); + } + + private void assertMappingsEqual(String expected, String actual) throws IOException { + + XContentParser expectedJson = createParser(XContentType.JSON.xContent(), expected); + XContentParser actualJson = createParser(XContentType.JSON.xContent(), actual); + assertEquals(expectedJson.mapOrdered(), actualJson.mapOrdered()); + } + + /** + * Returns a random {@link PutMappingRequest}. + */ + private static PutMappingRequest createTestItem() throws IOException { + String index = randomAlphaOfLength(5); + + PutMappingRequest request = new PutMappingRequest(index); + + String type = randomAlphaOfLength(5); + request.type(type); + request.source(randomMapping()); + + return request; + } + + private static XContentBuilder randomMapping() throws IOException { + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.startObject(); + + if (randomBoolean()) { + randomMappingFields(builder, true); + } + + builder.endObject(); + return builder; + } + + private static void randomMappingFields(XContentBuilder builder, boolean allowObjectField) throws IOException { + builder.startObject("properties"); + + int fieldsNo = randomIntBetween(0, 5); + for (int i = 0; i < fieldsNo; i++) { + builder.startObject(randomAlphaOfLength(5)); + + if (allowObjectField && randomBoolean()) { + randomMappingFields(builder, false); + } else { + builder.field("type", "text"); + } + + builder.endObject(); + } + + builder.endObject(); + } } diff --git a/core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java b/core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java new file mode 100644 index 0000000000000..a52969c628106 --- /dev/null +++ b/core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java @@ -0,0 +1,85 @@ +/* + * 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.action.admin.indices.mapping.put; + +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.test.ESTestCase; + +import java.io.IOException; + +import static org.elasticsearch.test.XContentTestUtils.insertRandomFields; + +public class PutMappingResponseTests extends ESTestCase { + + public void testToXContent() { + PutMappingResponse response = new PutMappingResponse(true); + String output = Strings.toString(response); + assertEquals("{\"acknowledged\":true}", output); + } + + public void testToAndFromXContent() throws IOException { + doFromXContentTestWithRandomFields(false); + } + + /** + * This test adds random fields and objects to the xContent rendered out to + * ensure we can parse it back to be forward compatible with additions to + * the xContent + */ + public void testFromXContentWithRandomFields() throws IOException { + doFromXContentTestWithRandomFields(true); + } + + private void doFromXContentTestWithRandomFields(boolean addRandomFields) throws IOException { + + final PutMappingResponse putMappingResponse = createTestItem(); + + boolean humanReadable = randomBoolean(); + final XContentType xContentType = randomFrom(XContentType.values()); + BytesReference originalBytes = toShuffledXContent(putMappingResponse, xContentType, ToXContent.EMPTY_PARAMS, humanReadable); + + BytesReference mutated; + if (addRandomFields) { + mutated = insertRandomFields(xContentType, originalBytes, null, random()); + } else { + mutated = originalBytes; + } + PutMappingResponse parsedPutMappingResponse; + try (XContentParser parser = createParser(xContentType.xContent(), mutated)) { + parsedPutMappingResponse = PutMappingResponse.fromXContent(parser); + assertNull(parser.nextToken()); + } + + assertEquals(putMappingResponse.isAcknowledged(), parsedPutMappingResponse.isAcknowledged()); + } + + /** + * Returns a random {@link PutMappingResponse}. + */ + private static PutMappingResponse createTestItem() throws IOException { + boolean acknowledged = randomBoolean(); + + return new PutMappingResponse(acknowledged); + } +} From c0385c1768834a589c2c62bc2db5732ca26247b1 Mon Sep 17 00:00:00 2001 From: Catalin Ursachi Date: Tue, 19 Dec 2017 10:45:19 +0000 Subject: [PATCH 2/7] Fixed comments --- .../src/main/java/org/elasticsearch/client/IndicesClient.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 5d673fe10cc03..3b45d15bbc7a5 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 @@ -92,7 +92,7 @@ public void createIndexAsync(CreateIndexRequest createIndexRequest, ActionListen } /** - * Creates an index using the Put Mapping API + * Updates the mappings on an index using the Put Mapping API *

* See * Put Mapping API on elastic.co @@ -103,7 +103,7 @@ public PutMappingResponse putMapping(PutMappingRequest putMappingRequest, Header } /** - * Asynchronously creates an index using the Put Mapping API + * Asynchronously updates the mappings on an index using the Put Mapping API *

* See * Put Mapping API on elastic.co From 658eb7ac9fec8c6b64a59adc5b59c8a8052eee1b Mon Sep 17 00:00:00 2001 From: Catalin Ursachi Date: Sat, 20 Jan 2018 23:25:44 +0000 Subject: [PATCH 3/7] Review mark-ups --- .../main/java/org/elasticsearch/client/Request.java | 3 +++ .../indices/mapping/put/PutMappingRequestTests.java | 12 ++++++++++++ 2 files changed, 15 insertions(+) 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 6c99472ca25ed..f3af7b308ada2 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 @@ -167,6 +167,9 @@ static Request createIndex(CreateIndexRequest createIndexRequest) throws IOExcep } static Request putMapping(PutMappingRequest putMappingRequest) throws IOException { + // The concreteIndex is an internal concept, not applicable to requests made over the REST API. + assert (putMappingRequest.getConcreteIndex() == null); + String endpoint = endpoint(putMappingRequest.indices(), "_mapping", putMappingRequest.type()); Params parameters = Params.builder(); diff --git a/core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java b/core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java index 93c9b707df415..9b626105fdc34 100644 --- a/core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java +++ b/core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java @@ -124,6 +124,18 @@ public void testToXContent() throws IOException { assertEquals(expectedRequestBody, actualRequestBody); } + public void testToXContentWithEmptySource() throws IOException { + PutMappingRequest request = new PutMappingRequest("foo"); + + request.type("my_type"); + + String actualRequestBody = Strings.toString(request); + + String expectedRequestBody = "{}"; + + assertEquals(expectedRequestBody, actualRequestBody); + } + public void testToAndFromXContent() throws IOException { final PutMappingRequest putMappingRequest = createTestItem(); From 6a003107181ded875e3220c2fa1603df2502a50b Mon Sep 17 00:00:00 2001 From: Catalin Ursachi Date: Sun, 21 Jan 2018 16:26:10 +0000 Subject: [PATCH 4/7] Moved PutMappingResponseTests --- .../action/admin/indices/mapping/put/PutMappingResponseTests.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {core => server}/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java (100%) diff --git a/core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java similarity index 100% rename from core/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java rename to server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingResponseTests.java From b7a110e2f0cf779f2d588d0ef3067903ff739e63 Mon Sep 17 00:00:00 2001 From: Catalin Ursachi Date: Sun, 21 Jan 2018 18:25:07 +0000 Subject: [PATCH 5/7] Added Put Mapping docs --- .../IndicesClientDocumentationIT.java | 100 ++++++++++++++++-- docs/java-rest/high-level/apis/index.asciidoc | 2 + .../high-level/apis/putmapping.asciidoc | 71 +++++++++++++ .../high-level/supported-apis.asciidoc | 1 + 4 files changed, 165 insertions(+), 9 deletions(-) create mode 100644 docs/java-rest/high-level/apis/putmapping.asciidoc 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 bc3b1698f9679..f6ea4afb21e9a 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 @@ -28,6 +28,8 @@ 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.mapping.put.PutMappingRequest; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexResponse; import org.elasticsearch.action.support.ActiveShardCount; @@ -157,15 +159,15 @@ public void testCreateIndex() throws IOException { // tag::create-index-request-mappings request.mapping("tweet", // <1> - " {\n" + - " \"tweet\": {\n" + - " \"properties\": {\n" + - " \"message\": {\n" + - " \"type\": \"text\"\n" + - " }\n" + - " }\n" + - " }\n" + - " }", // <2> + "{\n" + + " \"tweet\": {\n" + + " \"properties\": {\n" + + " \"message\": {\n" + + " \"type\": \"text\"\n" + + " }\n" + + " }\n" + + " }\n" + + "}", // <2> XContentType.JSON); // end::create-index-request-mappings @@ -228,6 +230,86 @@ public void onFailure(Exception e) { } } + public void testPutMapping() throws IOException { + RestHighLevelClient client = highLevelClient(); + + { + CreateIndexResponse createIndexResponse = client.indices().create(new CreateIndexRequest("twitter")); + assertTrue(createIndexResponse.isAcknowledged()); + } + + { + // tag::put-mapping-request + PutMappingRequest request = new PutMappingRequest("twitter"); // <1> + request.type("tweet"); // <2> + // end::put-mapping-request + + // tag::put-mapping-request-source + request.source( + "{\n" + + " \"tweet\": {\n" + + " \"properties\": {\n" + + " \"message\": {\n" + + " \"type\": \"text\"\n" + + " }\n" + + " }\n" + + " }\n" + + "}", // <1> + XContentType.JSON); + // end::put-mapping-request-source + + // tag::put-mapping-request-timeout + request.timeout(TimeValue.timeValueMinutes(2)); // <1> + request.timeout("2m"); // <2> + // end::put-mapping-request-timeout + // tag::put-mapping-request-masterTimeout + request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1> + request.masterNodeTimeout("1m"); // <2> + // end::put-mapping-request-masterTimeout + + // tag::put-mapping-execute + PutMappingResponse putMappingResponse = client.indices().putMapping(request); + // end::put-mapping-execute + + // tag::put-mapping-response + boolean acknowledged = putMappingResponse.isAcknowledged(); // <1> + // end::put-mapping-response + assertTrue(acknowledged); + } + } + + public void testPutMappingAsync() throws Exception { + final RestHighLevelClient client = highLevelClient(); + + { + CreateIndexResponse createIndexResponse = client.indices().create(new CreateIndexRequest("twitter")); + assertTrue(createIndexResponse.isAcknowledged()); + } + + { + PutMappingRequest request = new PutMappingRequest("twitter").type("tweet"); + // tag::put-mapping-execute-async + client.indices().putMappingAsync(request, new ActionListener() { + @Override + public void onResponse(PutMappingResponse putMappingResponse) { + // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }); + // end::put-mapping-execute-async + + assertBusy(() -> { + // TODO Use Indices Exist API instead once it exists + Response response = client.getLowLevelClient().performRequest("HEAD", "twitter"); + assertTrue(RestStatus.OK.getStatus() == response.getStatusLine().getStatusCode()); + }); + } + } + public void testOpenIndex() 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 f6da998a8476f..f7367b6e8c26d 100644 --- a/docs/java-rest/high-level/apis/index.asciidoc +++ b/docs/java-rest/high-level/apis/index.asciidoc @@ -6,6 +6,8 @@ include::open_index.asciidoc[] include::close_index.asciidoc[] +include::putmapping.asciidoc[] + include::_index.asciidoc[] include::get.asciidoc[] diff --git a/docs/java-rest/high-level/apis/putmapping.asciidoc b/docs/java-rest/high-level/apis/putmapping.asciidoc new file mode 100644 index 0000000000000..57b8ec8964a9a --- /dev/null +++ b/docs/java-rest/high-level/apis/putmapping.asciidoc @@ -0,0 +1,71 @@ +[[java-rest-high-put-mapping]] +=== Put Mapping API + +[[java-rest-high-put-mapping-request]] +==== Put Mapping Request + +A `PutMappingRequest` requires an `index` argument, and a type: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-request] +-------------------------------------------------- +<1> The index to add the mapping to +<2> The type to create (or update) + +==== Mapping source +A description of the fields to create on the mapping; if not defined, the mapping will default to empty. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-request-source] +-------------------------------------------------- +<1> The mapping source + +==== Optional arguments +The following arguments can optionally be provided: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-request-timeout] +-------------------------------------------------- +<1> Timeout to wait for the all the nodes to acknowledge the index creation as a `TimeValue` +<2> Timeout to wait for the all the nodes to acknowledge the index creation as a `String` + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-request-masterTimeout] +-------------------------------------------------- +<1> Timeout to connect to the master node as a `TimeValue` +<2> Timeout to connect to the master node as a `String` + +[[java-rest-high-put-mapping-sync]] +==== Synchronous Execution + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-execute] +-------------------------------------------------- + +[[java-rest-high-put-mapping-async]] +==== Asynchronous Execution + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-execute-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-put-mapping-response]] +==== Put Mapping Response + +The returned `PutMappingResponse` allows to retrieve information about the executed + operation as follows: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-mapping-response] +-------------------------------------------------- +<1> Indicates whether all of the nodes have acknowledged the request diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index fa71b62d64e70..aede4789f4dec 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -8,6 +8,7 @@ Indices APIs:: * <> * <> * <> +* <> Single document APIs:: * <> From ca458e5647fb95868929f776207e94016b815bb5 Mon Sep 17 00:00:00 2001 From: Catalin Ursachi Date: Mon, 22 Jan 2018 17:58:14 +0000 Subject: [PATCH 6/7] Review mark-ups --- .../org/elasticsearch/client/Request.java | 5 +-- .../elasticsearch/client/IndicesClientIT.java | 3 -- .../elasticsearch/client/RequestTests.java | 8 ----- .../IndicesClientDocumentationIT.java | 32 +++++++++---------- .../create/CreateIndexRequestTests.java | 2 +- .../mapping/put/PutMappingRequestTests.java | 28 ++-------------- 6 files changed, 22 insertions(+), 56 deletions(-) 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 8566a7c6a4c61..229e45498aa95 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 @@ -181,14 +181,15 @@ static Request createIndex(CreateIndexRequest createIndexRequest) throws IOExcep static Request putMapping(PutMappingRequest putMappingRequest) throws IOException { // The concreteIndex is an internal concept, not applicable to requests made over the REST API. - assert (putMappingRequest.getConcreteIndex() == null); + if (putMappingRequest.getConcreteIndex() != null) { + throw new IllegalArgumentException("concreteIndex cannot be set on PutMapping requests made over the REST API"); + } String endpoint = endpoint(putMappingRequest.indices(), "_mapping", putMappingRequest.type()); Params parameters = Params.builder(); parameters.withTimeout(putMappingRequest.timeout()); parameters.withMasterTimeout(putMappingRequest.masterNodeTimeout()); - parameters.withUpdateAllTypes(putMappingRequest.updateAllTypes()); HttpEntity entity = createEntity(putMappingRequest, REQUEST_BODY_CONTENT_TYPE); return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity); 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 cd55eeabb318d..2f81479f93a64 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 @@ -118,9 +118,7 @@ public void testPutMapping() throws IOException { createIndex(indexName); PutMappingRequest putMappingRequest = new PutMappingRequest(indexName); - putMappingRequest.type("type_name"); - XContentBuilder mappingBuilder = JsonXContent.contentBuilder(); mappingBuilder.startObject().startObject("properties").startObject("field"); mappingBuilder.field("type", "text"); @@ -132,7 +130,6 @@ public void testPutMapping() throws IOException { assertTrue(putMappingResponse.isAcknowledged()); Map indexMetaData = getIndexMetadata(indexName); - Map mappingsData = (Map) indexMetaData.get("mappings"); Map typeData = (Map) mappingsData.get("type_name"); Map properties = (Map) typeData.get("properties"); 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 b52bb30650cc7..0ddaf1de1ca52 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 @@ -336,14 +336,6 @@ public void testPutMapping() throws IOException { setRandomTimeout(putMappingRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams); setRandomMasterTimeout(putMappingRequest, expectedParams); - if (randomBoolean()) { - boolean updateAllTypes = randomBoolean(); - putMappingRequest.updateAllTypes(updateAllTypes); - if (updateAllTypes) { - expectedParams.put("update_all_types", Boolean.TRUE.toString()); - } - } - Request request = Request.putMapping(putMappingRequest); StringJoiner endpoint = new StringJoiner("/", "/", ""); String index = String.join(",", indices); 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 f6ea4afb21e9a..23029c7c6b007 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 @@ -160,14 +160,14 @@ public void testCreateIndex() throws IOException { // tag::create-index-request-mappings request.mapping("tweet", // <1> "{\n" + - " \"tweet\": {\n" + - " \"properties\": {\n" + - " \"message\": {\n" + - " \"type\": \"text\"\n" + - " }\n" + - " }\n" + - " }\n" + - "}", // <2> + " \"tweet\": {\n" + + " \"properties\": {\n" + + " \"message\": {\n" + + " \"type\": \"text\"\n" + + " }\n" + + " }\n" + + " }\n" + + "}", // <2> XContentType.JSON); // end::create-index-request-mappings @@ -247,14 +247,14 @@ public void testPutMapping() throws IOException { // tag::put-mapping-request-source request.source( "{\n" + - " \"tweet\": {\n" + - " \"properties\": {\n" + - " \"message\": {\n" + - " \"type\": \"text\"\n" + - " }\n" + - " }\n" + - " }\n" + - "}", // <1> + " \"tweet\": {\n" + + " \"properties\": {\n" + + " \"message\": {\n" + + " \"type\": \"text\"\n" + + " }\n" + + " }\n" + + " }\n" + + "}", // <1> XContentType.JSON); // end::put-mapping-request-source diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java index 633034b58a602..d7553ebf07cda 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/create/CreateIndexRequestTests.java @@ -201,7 +201,7 @@ private static XContentBuilder randomMapping(String type) throws IOException { return builder; } - private static void randomMappingFields(XContentBuilder builder, boolean allowObjectField) throws IOException { + public static void randomMappingFields(XContentBuilder builder, boolean allowObjectField) throws IOException { builder.startObject("properties"); int fieldsNo = randomIntBetween(0, 5); diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java index 9b626105fdc34..d31cfd13fc904 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java @@ -38,6 +38,7 @@ import java.io.IOException; +import org.elasticsearch.action.admin.indices.create.CreateIndexRequestTests; import static org.elasticsearch.common.xcontent.ToXContent.EMPTY_PARAMS; public class PutMappingRequestTests extends ESTestCase { @@ -105,7 +106,6 @@ public void testPutMappingRequestSerialization() throws IOException { public void testToXContent() throws IOException { PutMappingRequest request = new PutMappingRequest("foo"); - request.type("my_type"); XContentBuilder mapping = JsonXContent.contentBuilder().startObject(); @@ -118,21 +118,16 @@ public void testToXContent() throws IOException { request.source(mapping); String actualRequestBody = Strings.toString(request); - String expectedRequestBody = "{\"properties\":{\"email\":{\"type\":\"text\"}}}"; - assertEquals(expectedRequestBody, actualRequestBody); } public void testToXContentWithEmptySource() throws IOException { PutMappingRequest request = new PutMappingRequest("foo"); - request.type("my_type"); String actualRequestBody = Strings.toString(request); - String expectedRequestBody = "{}"; - assertEquals(expectedRequestBody, actualRequestBody); } @@ -177,29 +172,10 @@ private static XContentBuilder randomMapping() throws IOException { builder.startObject(); if (randomBoolean()) { - randomMappingFields(builder, true); + CreateIndexRequestTests.randomMappingFields(builder, true); } builder.endObject(); return builder; } - - private static void randomMappingFields(XContentBuilder builder, boolean allowObjectField) throws IOException { - builder.startObject("properties"); - - int fieldsNo = randomIntBetween(0, 5); - for (int i = 0; i < fieldsNo; i++) { - builder.startObject(randomAlphaOfLength(5)); - - if (allowObjectField && randomBoolean()) { - randomMappingFields(builder, false); - } else { - builder.field("type", "text"); - } - - builder.endObject(); - } - - builder.endObject(); - } } From b9ec26bf9c7adcbce17cdbe982e4b111630e0635 Mon Sep 17 00:00:00 2001 From: Catalin Ursachi Date: Mon, 22 Jan 2018 17:59:52 +0000 Subject: [PATCH 7/7] Fixed import order --- .../admin/indices/mapping/put/PutMappingRequestTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java index d31cfd13fc904..902dc1870934c 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/mapping/put/PutMappingRequestTests.java @@ -21,6 +21,7 @@ import org.elasticsearch.Version; import org.elasticsearch.action.ActionRequestValidationException; +import org.elasticsearch.action.admin.indices.create.CreateIndexRequestTests; import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesReference; @@ -38,7 +39,6 @@ import java.io.IOException; -import org.elasticsearch.action.admin.indices.create.CreateIndexRequestTests; import static org.elasticsearch.common.xcontent.ToXContent.EMPTY_PARAMS; public class PutMappingRequestTests extends ESTestCase {