فهرست منبع

Deprecate types in update requests. (#36181)

The following updates were made:
* Add deprecation warnings to `RestUpdateAction`, plus a test in `RestUpdateActionTests`.
* Deprecate relevant methods on the Java HLRC requests/ responses.
* Add HLRC integration tests for the typed APIs.
* Update documentation (for both the REST API and Java HLRC).
* Fix failing integration tests.

Because of an earlier PR, the REST yml tests were already updated (one version without types, and another legacy version that retains types).
Julie Tibshirani 6 سال پیش
والد
کامیت
ccd1beb9b3

+ 4 - 1
client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java

@@ -70,6 +70,7 @@ import org.elasticsearch.common.xcontent.XContentHelper;
 import org.elasticsearch.common.xcontent.XContentParser;
 import org.elasticsearch.common.xcontent.XContentType;
 import org.elasticsearch.index.VersionType;
+import org.elasticsearch.index.mapper.MapperService;
 import org.elasticsearch.index.rankeval.RankEvalRequest;
 import org.elasticsearch.index.reindex.AbstractBulkByScrollRequest;
 import org.elasticsearch.index.reindex.DeleteByQueryRequest;
@@ -316,7 +317,9 @@ final class RequestConverters {
     }
 
     static Request update(UpdateRequest updateRequest) throws IOException {
-        String endpoint = endpoint(updateRequest.index(), updateRequest.type(), updateRequest.id(), "_update");
+        String endpoint = updateRequest.type().equals(MapperService.SINGLE_MAPPING_NAME)
+            ? endpoint(updateRequest.index(), "_update", updateRequest.id())
+            : endpoint(updateRequest.index(), updateRequest.type(), updateRequest.id(), "_update");
         Request request = new Request(HttpPost.METHOD_NAME, endpoint);
 
         Params parameters = new Params(request);

+ 102 - 12
client/rest-high-level/src/test/java/org/elasticsearch/client/CrudIT.java

@@ -65,6 +65,10 @@ import org.elasticsearch.index.reindex.DeleteByQueryRequest;
 import org.elasticsearch.index.reindex.UpdateByQueryAction;
 import org.elasticsearch.index.reindex.UpdateByQueryRequest;
 import org.elasticsearch.rest.RestStatus;
+import org.elasticsearch.rest.action.document.RestDeleteAction;
+import org.elasticsearch.rest.action.document.RestGetAction;
+import org.elasticsearch.rest.action.document.RestMultiGetAction;
+import org.elasticsearch.rest.action.document.RestUpdateAction;
 import org.elasticsearch.script.Script;
 import org.elasticsearch.script.ScriptType;
 import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
@@ -173,6 +177,23 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
         }
     }
 
+    public void testDeleteWithTypes() throws IOException {
+        String docId = "id";
+        highLevelClient().index(new IndexRequest("index", "type", docId)
+            .source(Collections.singletonMap("foo", "bar")), RequestOptions.DEFAULT);
+
+        DeleteRequest deleteRequest = new DeleteRequest("index", "type", docId);
+        DeleteResponse deleteResponse = execute(deleteRequest,
+            highLevelClient()::delete,
+            highLevelClient()::deleteAsync,
+            expectWarnings(RestDeleteAction.TYPES_DEPRECATION_MESSAGE));
+
+        assertEquals("index", deleteResponse.getIndex());
+        assertEquals("type", deleteResponse.getType());
+        assertEquals(docId, deleteResponse.getId());
+        assertEquals(DocWriteResponse.Result.DELETED, deleteResponse.getResult());
+    }
+
     public void testExists() throws IOException {
         {
             GetRequest getRequest = new GetRequest("index", "id");
@@ -331,6 +352,29 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
         }
     }
 
+    public void testGetWithTypes() throws IOException {
+        String document = "{\"field\":\"value\"}";
+        IndexRequest index = new IndexRequest("index", "type", "id");
+        index.source(document, XContentType.JSON);
+        index.setRefreshPolicy(RefreshPolicy.IMMEDIATE);
+        highLevelClient().index(index, RequestOptions.DEFAULT);
+
+        GetRequest getRequest = new GetRequest("index", "type", "id");
+        GetResponse getResponse = execute(getRequest,
+            highLevelClient()::get,
+            highLevelClient()::getAsync,
+            expectWarnings(RestGetAction.TYPES_DEPRECATION_MESSAGE));
+
+        assertEquals("index", getResponse.getIndex());
+        assertEquals("type", getResponse.getType());
+        assertEquals("id", getResponse.getId());
+
+        assertTrue(getResponse.isExists());
+        assertFalse(getResponse.isSourceEmpty());
+        assertEquals(1L, getResponse.getVersion());
+        assertEquals(document, getResponse.getSourceAsString());
+    }
+
     public void testMultiGet() throws IOException {
         {
             MultiGetRequest multiGetRequest = new MultiGetRequest();
@@ -387,6 +431,36 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
         }
     }
 
+    public void testMultiGetWithTypes() throws IOException {
+        BulkRequest bulk = new BulkRequest();
+        bulk.setRefreshPolicy(RefreshPolicy.IMMEDIATE);
+        bulk.add(new IndexRequest("index", "type", "id1")
+            .source("{\"field\":\"value1\"}", XContentType.JSON));
+        bulk.add(new IndexRequest("index", "type", "id2")
+            .source("{\"field\":\"value2\"}", XContentType.JSON));
+
+        highLevelClient().bulk(bulk, RequestOptions.DEFAULT);
+        MultiGetRequest multiGetRequest = new MultiGetRequest();
+        multiGetRequest.add("index", "id1");
+        multiGetRequest.add("index", "type", "id2");
+
+        MultiGetResponse response = execute(multiGetRequest,
+            highLevelClient()::mget,
+            highLevelClient()::mgetAsync,
+            expectWarnings(RestMultiGetAction.TYPES_DEPRECATION_MESSAGE));
+        assertEquals(2, response.getResponses().length);
+
+        GetResponse firstResponse = response.getResponses()[0].getResponse();
+        assertEquals("index", firstResponse.getIndex());
+        assertEquals("type", firstResponse.getType());
+        assertEquals("id1", firstResponse.getId());
+
+        GetResponse secondResponse = response.getResponses()[1].getResponse();
+        assertEquals("index", secondResponse.getIndex());
+        assertEquals("type", secondResponse.getType());
+        assertEquals("id2", secondResponse.getId());
+    }
+
     public void testIndex() throws IOException {
         final XContentType xContentType = randomFrom(XContentType.values());
         {
@@ -492,7 +566,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
 
     public void testUpdate() throws IOException {
         {
-            UpdateRequest updateRequest = new UpdateRequest("index", "_doc", "does_not_exist");
+            UpdateRequest updateRequest = new UpdateRequest("index", "does_not_exist");
             updateRequest.doc(singletonMap("field", "value"), randomFrom(XContentType.values()));
 
             ElasticsearchStatusException exception = expectThrows(ElasticsearchStatusException.class, () ->
@@ -507,14 +581,14 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
             IndexResponse indexResponse = highLevelClient().index(indexRequest, RequestOptions.DEFAULT);
             assertEquals(RestStatus.CREATED, indexResponse.status());
 
-            UpdateRequest updateRequest = new UpdateRequest("index", "_doc", "id");
+            UpdateRequest updateRequest = new UpdateRequest("index", "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", "_doc", "id");
+            UpdateRequest updateRequestConflict = new UpdateRequest("index", "id");
             updateRequestConflict.doc(singletonMap("field", "with_version_conflict"), randomFrom(XContentType.values()));
             updateRequestConflict.version(indexResponse.getVersion());
 
@@ -530,7 +604,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
             IndexResponse indexResponse = highLevelClient().index(indexRequest, RequestOptions.DEFAULT);
             assertEquals(RestStatus.CREATED, indexResponse.status());
 
-            UpdateRequest updateRequest = new UpdateRequest("index", "_doc", "with_script");
+            UpdateRequest updateRequest = new UpdateRequest("index", "with_script");
             Script script = new Script(ScriptType.INLINE, "painless", "ctx._source.counter += params.count", singletonMap("count", 8));
             updateRequest.script(script);
             updateRequest.fetchSource(true);
@@ -551,7 +625,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
             assertEquals(RestStatus.CREATED, indexResponse.status());
             assertEquals(12L, indexResponse.getVersion());
 
-            UpdateRequest updateRequest = new UpdateRequest("index", "_doc", "with_doc");
+            UpdateRequest updateRequest = new UpdateRequest("index", "with_doc");
             updateRequest.doc(singletonMap("field_2", "two"), randomFrom(XContentType.values()));
             updateRequest.fetchSource("field_*", "field_3");
 
@@ -573,7 +647,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
             assertEquals(RestStatus.CREATED, indexResponse.status());
             assertEquals(1L, indexResponse.getVersion());
 
-            UpdateRequest updateRequest = new UpdateRequest("index", "_doc", "noop");
+            UpdateRequest updateRequest = new UpdateRequest("index", "noop");
             updateRequest.doc(singletonMap("field", "value"), randomFrom(XContentType.values()));
 
             UpdateResponse updateResponse = execute(updateRequest, highLevelClient()::update, highLevelClient()::updateAsync);
@@ -589,7 +663,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
             assertEquals(2L, updateResponse.getVersion());
         }
         {
-            UpdateRequest updateRequest = new UpdateRequest("index", "_doc", "with_upsert");
+            UpdateRequest updateRequest = new UpdateRequest("index", "with_upsert");
             updateRequest.upsert(singletonMap("doc_status", "created"));
             updateRequest.doc(singletonMap("doc_status", "updated"));
             updateRequest.fetchSource(true);
@@ -604,7 +678,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
             assertEquals("created", getResult.sourceAsMap().get("doc_status"));
         }
         {
-            UpdateRequest updateRequest = new UpdateRequest("index", "_doc", "with_doc_as_upsert");
+            UpdateRequest updateRequest = new UpdateRequest("index", "with_doc_as_upsert");
             updateRequest.doc(singletonMap("field", "initialized"));
             updateRequest.fetchSource(true);
             updateRequest.docAsUpsert(true);
@@ -619,7 +693,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
             assertEquals("initialized", getResult.sourceAsMap().get("field"));
         }
         {
-            UpdateRequest updateRequest = new UpdateRequest("index", "_doc", "with_scripted_upsert");
+            UpdateRequest updateRequest = new UpdateRequest("index", "with_scripted_upsert");
             updateRequest.fetchSource(true);
             updateRequest.script(new Script(ScriptType.INLINE, "painless", "ctx._source.level = params.test", singletonMap("test", "C")));
             updateRequest.scriptedUpsert(true);
@@ -637,7 +711,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
         }
         {
             IllegalStateException exception = expectThrows(IllegalStateException.class, () -> {
-                UpdateRequest updateRequest = new UpdateRequest("index", "_doc", "id");
+                UpdateRequest updateRequest = new UpdateRequest("index", "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);
@@ -647,6 +721,22 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
         }
     }
 
+    public void testUpdateWithTypes() throws IOException {
+        IndexRequest indexRequest = new IndexRequest("index", "type", "id");
+        indexRequest.source(singletonMap("field", "value"));
+        IndexResponse indexResponse = highLevelClient().index(indexRequest, RequestOptions.DEFAULT);
+
+        UpdateRequest updateRequest = new UpdateRequest("index", "type", "id");
+        updateRequest.doc(singletonMap("field", "updated"), randomFrom(XContentType.values()));
+        UpdateResponse updateResponse = execute(updateRequest,
+            highLevelClient()::update,
+            highLevelClient()::updateAsync,
+            expectWarnings(RestUpdateAction.TYPES_DEPRECATION_MESSAGE));
+
+        assertEquals(RestStatus.OK, updateResponse.status());
+        assertEquals(indexResponse.getVersion() + 1, updateResponse.getVersion());
+    }
+
     public void testBulk() throws IOException {
         int nbItems = randomIntBetween(10, 100);
         boolean[] errors = new boolean[nbItems];
@@ -687,7 +777,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
                     bulkRequest.add(createRequest);
 
                 } else if (opType == DocWriteRequest.OpType.UPDATE) {
-                    UpdateRequest updateRequest = new UpdateRequest("index", "_doc", id)
+                    UpdateRequest updateRequest = new UpdateRequest("index", id)
                             .doc(new IndexRequest().source(source, xContentType));
                     if (erroneous == false) {
                         assertEquals(RestStatus.CREATED,
@@ -996,7 +1086,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
                         processor.add(createRequest);
 
                     } else if (opType == DocWriteRequest.OpType.UPDATE) {
-                        UpdateRequest updateRequest = new UpdateRequest("index", "_doc", id)
+                        UpdateRequest updateRequest = new UpdateRequest("index", id)
                                 .doc(new IndexRequest().source(xContentType, "id", i));
                         if (erroneous == false) {
                             assertEquals(RestStatus.CREATED,

+ 19 - 3
client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java

@@ -630,10 +630,9 @@ public class RequestConvertersTests extends ESTestCase {
 
         Map<String, String> expectedParams = new HashMap<>();
         String index = randomAlphaOfLengthBetween(3, 10);
-        String type = randomAlphaOfLengthBetween(3, 10);
         String id = randomAlphaOfLengthBetween(3, 10);
 
-        UpdateRequest updateRequest = new UpdateRequest(index, type, id);
+        UpdateRequest updateRequest = new UpdateRequest(index, id);
         updateRequest.detectNoop(randomBoolean());
 
         if (randomBoolean()) {
@@ -687,7 +686,7 @@ public class RequestConvertersTests extends ESTestCase {
         }
 
         Request request = RequestConverters.update(updateRequest);
-        assertEquals("/" + index + "/" + type + "/" + id + "/_update", request.getEndpoint());
+        assertEquals("/" + index + "/_update/" + id, request.getEndpoint());
         assertEquals(expectedParams, request.getParameters());
         assertEquals(HttpPost.METHOD_NAME, request.getMethod());
 
@@ -718,6 +717,23 @@ public class RequestConvertersTests extends ESTestCase {
         }
     }
 
+    public void testUpdateWithType() throws IOException {
+        String index = randomAlphaOfLengthBetween(3, 10);
+        String type = randomAlphaOfLengthBetween(3, 10);
+        String id = randomAlphaOfLengthBetween(3, 10);
+
+        UpdateRequest updateRequest = new UpdateRequest(index, type, id);
+
+        XContentType xContentType = XContentType.JSON;
+        BytesReference source = RandomObjects.randomSource(random(), xContentType);
+        updateRequest.doc(new IndexRequest().source(source, xContentType));
+
+        Request request = RequestConverters.update(updateRequest);
+        assertEquals("/" + index + "/" + type + "/" + id + "/_update", request.getEndpoint());
+        assertEquals(HttpPost.METHOD_NAME, request.getMethod());
+        assertToXContentBody(updateRequest, request.getEntity());
+    }
+
     public void testUpdateWithDifferentContentTypes() {
         IllegalStateException exception = expectThrows(IllegalStateException.class, () -> {
             UpdateRequest updateRequest = new UpdateRequest();

+ 14 - 16
client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CRUDDocumentationIT.java

@@ -296,8 +296,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
             //tag::update-request
             UpdateRequest request = new UpdateRequest(
                     "posts", // <1>
-                    "_doc",  // <2>
-                    "1");   // <3>
+                    "1");   // <2>
             //end::update-request
             request.fetchSource(true);
             //tag::update-request-with-inline-script
@@ -311,7 +310,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
             assertEquals(DocWriteResponse.Result.UPDATED, updateResponse.getResult());
             assertEquals(4, updateResponse.getGetResult().getSource().get("field"));
 
-            request = new UpdateRequest("posts", "_doc", "1").fetchSource(true);
+            request = new UpdateRequest("posts", "1").fetchSource(true);
             //tag::update-request-with-stored-script
             Script stored = new Script(
                     ScriptType.STORED, null, "increment-field", parameters);  // <1>
@@ -326,7 +325,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
             Map<String, Object> jsonMap = new HashMap<>();
             jsonMap.put("updated", new Date());
             jsonMap.put("reason", "daily update");
-            UpdateRequest request = new UpdateRequest("posts", "_doc", "1")
+            UpdateRequest request = new UpdateRequest("posts", "1")
                     .doc(jsonMap); // <1>
             //end::update-request-with-doc-as-map
             UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);
@@ -341,7 +340,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
                 builder.field("reason", "daily update");
             }
             builder.endObject();
-            UpdateRequest request = new UpdateRequest("posts", "_doc", "1")
+            UpdateRequest request = new UpdateRequest("posts", "1")
                     .doc(builder);  // <1>
             //end::update-request-with-doc-as-xcontent
             UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);
@@ -349,7 +348,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
         }
         {
             //tag::update-request-shortcut
-            UpdateRequest request = new UpdateRequest("posts", "_doc", "1")
+            UpdateRequest request = new UpdateRequest("posts", "1")
                     .doc("updated", new Date(),
                          "reason", "daily update"); // <1>
             //end::update-request-shortcut
@@ -358,7 +357,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
         }
         {
             //tag::update-request-with-doc-as-string
-            UpdateRequest request = new UpdateRequest("posts", "_doc", "1");
+            UpdateRequest request = new UpdateRequest("posts", "1");
             String jsonString = "{" +
                     "\"updated\":\"2017-01-01\"," +
                     "\"reason\":\"daily update\"" +
@@ -374,7 +373,6 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
 
             // tag::update-response
             String index = updateResponse.getIndex();
-            String type = updateResponse.getType();
             String id = updateResponse.getId();
             long version = updateResponse.getVersion();
             if (updateResponse.getResult() == DocWriteResponse.Result.CREATED) {
@@ -415,7 +413,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
         }
         {
             //tag::update-docnotfound
-            UpdateRequest request = new UpdateRequest("posts", "_doc", "does_not_exist")
+            UpdateRequest request = new UpdateRequest("posts", "does_not_exist")
                     .doc("field", "value");
             try {
                 UpdateResponse updateResponse = client.update(
@@ -429,7 +427,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
         }
         {
             // tag::update-conflict
-            UpdateRequest request = new UpdateRequest("posts", "_doc", "1")
+            UpdateRequest request = new UpdateRequest("posts", "1")
                     .doc("field", "value")
                     .version(1);
             try {
@@ -443,7 +441,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
             // end::update-conflict
         }
         {
-            UpdateRequest request = new UpdateRequest("posts", "_doc", "1").doc("reason", "no source");
+            UpdateRequest request = new UpdateRequest("posts", "1").doc("reason", "no source");
             //tag::update-request-no-source
             request.fetchSource(true); // <1>
             //end::update-request-no-source
@@ -453,7 +451,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
             assertEquals(3, updateResponse.getGetResult().sourceAsMap().size());
         }
         {
-            UpdateRequest request = new UpdateRequest("posts", "_doc", "1").doc("reason", "source includes");
+            UpdateRequest request = new UpdateRequest("posts", "1").doc("reason", "source includes");
             //tag::update-request-source-include
             String[] includes = new String[]{"updated", "r*"};
             String[] excludes = Strings.EMPTY_ARRAY;
@@ -468,7 +466,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
             assertTrue(sourceAsMap.containsKey("updated"));
         }
         {
-            UpdateRequest request = new UpdateRequest("posts", "_doc", "1").doc("reason", "source excludes");
+            UpdateRequest request = new UpdateRequest("posts", "1").doc("reason", "source excludes");
             //tag::update-request-source-exclude
             String[] includes = Strings.EMPTY_ARRAY;
             String[] excludes = new String[]{"updated"};
@@ -483,7 +481,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
             assertTrue(sourceAsMap.containsKey("field"));
         }
         {
-            UpdateRequest request = new UpdateRequest("posts", "_doc", "id");
+            UpdateRequest request = new UpdateRequest("posts", "id");
             // tag::update-request-routing
             request.routing("routing"); // <1>
             // end::update-request-routing
@@ -520,7 +518,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
             // end::update-request-active-shards
         }
         {
-            UpdateRequest request = new UpdateRequest("posts", "_doc", "async").doc("reason", "async update").docAsUpsert(true);
+            UpdateRequest request = new UpdateRequest("posts", "async").doc("reason", "async update").docAsUpsert(true);
 
             ActionListener<UpdateResponse> listener;
             // tag::update-execute-listener
@@ -695,7 +693,7 @@ public class CRUDDocumentationIT extends ESRestHighLevelClientTestCase {
             // tag::bulk-request-with-mixed-operations
             BulkRequest request = new BulkRequest();
             request.add(new DeleteRequest("posts", "3")); // <1>
-            request.add(new UpdateRequest("posts", "_doc", "2") // <2>
+            request.add(new UpdateRequest("posts", "2") // <2>
                     .doc(XContentType.JSON,"other", "test"));
             request.add(new IndexRequest("posts", "_doc", "4")  // <3>
                     .source(XContentType.JSON,"field", "baz"));

+ 1 - 1
distribution/archives/integ-test-zip/src/test/java/org/elasticsearch/test/rest/CreatedLocationHeaderIT.java

@@ -46,7 +46,7 @@ public class CreatedLocationHeaderIT extends ESRestTestCase {
     }
 
     public void testUpsert() throws IOException {
-        Request request = new Request("POST", "test/_doc/1/_update");
+        Request request = new Request("POST", "test/_update/1");
         request.setJsonEntity("{"
             + "\"doc\": {\"test\": \"test\"},"
             + "\"doc_as_upsert\": true}");

+ 1 - 1
distribution/archives/integ-test-zip/src/test/java/org/elasticsearch/test/rest/WaitForRefreshAndCloseIT.java

@@ -67,7 +67,7 @@ public class WaitForRefreshAndCloseIT extends ESRestTestCase {
         Request createDoc = new Request("PUT", docPath());
         createDoc.setJsonEntity("{\"test\":\"test\"}");
         client().performRequest(createDoc);
-        Request updateDoc = new Request("POST", docPath() + "/_update");
+        Request updateDoc = new Request("POST", "test/_update/1");
         updateDoc.setJsonEntity("{\"doc\":{\"name\":\"test\"}}");
         closeWhileListenerEngaged(start(updateDoc));
     }

+ 1 - 2
docs/java-rest/high-level/document/update.asciidoc

@@ -17,8 +17,7 @@ An +{request}+ requires the following arguments:
 include-tagged::{doc-tests-file}[{api}-request]
 --------------------------------------------------
 <1> Index
-<2> Type
-<3> Document id
+<2> Document id
 
 The Update API allows to update an existing document by using a script
 or by passing a partial document.

+ 2 - 0
qa/full-cluster-restart/src/test/java/org/elasticsearch/upgrades/FullClusterRestartIT.java

@@ -27,6 +27,7 @@ import org.elasticsearch.client.ResponseException;
 import org.elasticsearch.client.RestClient;
 import org.elasticsearch.index.mapper.TypeFieldMapper;
 import org.elasticsearch.rest.action.document.RestGetAction;
+import org.elasticsearch.rest.action.document.RestUpdateAction;
 import org.elasticsearch.rest.action.search.RestExplainAction;
 import org.elasticsearch.cluster.metadata.IndexMetaData;
 import org.elasticsearch.common.Booleans;
@@ -626,6 +627,7 @@ public class FullClusterRestartIT extends AbstractFullClusterRestartTestCase {
         String docId = (String) hit.get("_id");
 
         Request updateRequest = new Request("POST", "/" + index + "/doc/" + docId + "/_update");
+        updateRequest.setOptions(expectWarnings(RestUpdateAction.TYPES_DEPRECATION_MESSAGE));
         updateRequest.setJsonEntity("{ \"doc\" : { \"foo\": \"bar\"}}");
         client().performRequest(updateRequest);
 

+ 2 - 2
rest-api-spec/src/main/resources/rest-api-spec/api/update.json

@@ -3,8 +3,8 @@
     "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/docs-update.html",
     "methods": ["POST"],
     "url": {
-      "path": "/{index}/{type}/{id}/_update",
-      "paths": ["/{index}/{type}/{id}/_update", "/{index}/_doc/{id}/_update"],
+      "path": "/{index}/_update/{id}",
+      "paths": ["/{index}/_update/{id}", "/{index}/{type}/{id}/_update"],
       "parts": {
         "id": {
           "type": "string",

+ 17 - 1
server/src/main/java/org/elasticsearch/action/update/UpdateRequest.java

@@ -43,6 +43,7 @@ import org.elasticsearch.common.xcontent.XContentHelper;
 import org.elasticsearch.common.xcontent.XContentParser;
 import org.elasticsearch.common.xcontent.XContentType;
 import org.elasticsearch.index.VersionType;
+import org.elasticsearch.index.mapper.MapperService;
 import org.elasticsearch.index.shard.ShardId;
 import org.elasticsearch.script.Script;
 import org.elasticsearch.script.ScriptType;
@@ -90,7 +91,7 @@ public class UpdateRequest extends InstanceShardOperationRequest<UpdateRequest>
             ObjectParser.ValueType.OBJECT_ARRAY_BOOLEAN_OR_STRING);
     }
 
-    private String type;
+    private String type = MapperService.SINGLE_MAPPING_NAME;
     private String id;
     @Nullable
     private String routing;
@@ -121,6 +122,15 @@ public class UpdateRequest extends InstanceShardOperationRequest<UpdateRequest>
 
     }
 
+    public UpdateRequest(String index, String id) {
+        super(index);
+        this.id = id;
+    }
+
+    /**
+     * @deprecated Types are in the process of being removed. Use {@link #UpdateRequest(String, String)} instead.
+     */
+    @Deprecated
     public UpdateRequest(String index, String type, String id) {
         super(index);
         this.type = type;
@@ -173,7 +183,10 @@ public class UpdateRequest extends InstanceShardOperationRequest<UpdateRequest>
 
     /**
      * The type of the indexed document.
+     *
+     * @deprecated Types are in the process of being removed.
      */
+    @Deprecated
     @Override
     public String type() {
         return type;
@@ -181,7 +194,10 @@ public class UpdateRequest extends InstanceShardOperationRequest<UpdateRequest>
 
     /**
      * Sets the type of the indexed document.
+     *
+     * @deprecated Types are in the process of being removed.
      */
+    @Deprecated
     public UpdateRequest type(String type) {
         this.type = type;
         return this;

+ 1 - 1
server/src/main/java/org/elasticsearch/rest/action/document/RestDeleteAction.java

@@ -40,7 +40,7 @@ import static org.elasticsearch.rest.RestRequest.Method.DELETE;
 public class RestDeleteAction extends BaseRestHandler {
     private static final DeprecationLogger deprecationLogger = new DeprecationLogger(
         LogManager.getLogger(RestDeleteAction.class));
-    static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Specifying types in " +
+    public static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Specifying types in " +
         "document index requests is deprecated, use the /{index}/_doc/{id} endpoint instead.";
 
     public RestDeleteAction(Settings settings, RestController controller) {

+ 1 - 1
server/src/main/java/org/elasticsearch/rest/action/document/RestMultiGetAction.java

@@ -40,7 +40,7 @@ import static org.elasticsearch.rest.RestRequest.Method.POST;
 public class RestMultiGetAction extends BaseRestHandler {
     private static final DeprecationLogger deprecationLogger = new DeprecationLogger(
         LogManager.getLogger(RestMultiGetAction.class));
-    static final String TYPES_DEPRECATION_MESSAGE = "[types removal]" +
+    public static final String TYPES_DEPRECATION_MESSAGE = "[types removal]" +
         " Specifying types in multi get requests is deprecated.";
 
     private final boolean allowExplicitIndex;

+ 17 - 3
server/src/main/java/org/elasticsearch/rest/action/document/RestUpdateAction.java

@@ -19,10 +19,12 @@
 
 package org.elasticsearch.rest.action.document;
 
+import org.apache.logging.log4j.LogManager;
 import org.elasticsearch.action.index.IndexRequest;
 import org.elasticsearch.action.support.ActiveShardCount;
 import org.elasticsearch.action.update.UpdateRequest;
 import org.elasticsearch.client.node.NodeClient;
+import org.elasticsearch.common.logging.DeprecationLogger;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.index.VersionType;
 import org.elasticsearch.rest.BaseRestHandler;
@@ -37,9 +39,14 @@ import java.io.IOException;
 import static org.elasticsearch.rest.RestRequest.Method.POST;
 
 public class RestUpdateAction extends BaseRestHandler {
+    private static final DeprecationLogger deprecationLogger =
+        new DeprecationLogger(LogManager.getLogger(RestUpdateAction.class));
+    public static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Specifying types in " +
+        "document update requests is deprecated, use the endpoint /{index}/_update/{id} instead.";
 
     public RestUpdateAction(Settings settings, RestController controller) {
         super(settings);
+        controller.registerHandler(POST, "/{index}/_update/{id}", this);
         controller.registerHandler(POST, "/{index}/{type}/{id}/_update", this);
     }
 
@@ -50,9 +57,16 @@ public class RestUpdateAction extends BaseRestHandler {
 
     @Override
     public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
-        UpdateRequest updateRequest = new UpdateRequest(request.param("index"),
-            request.param("type"),
-            request.param("id"));
+        UpdateRequest updateRequest;
+        if (request.hasParam("type")) {
+            deprecationLogger.deprecatedAndMaybeLog("update_with_types", TYPES_DEPRECATION_MESSAGE);
+            updateRequest = new UpdateRequest(request.param("index"),
+                request.param("type"),
+                request.param("id"));
+        } else {
+            updateRequest = new UpdateRequest(request.param("index"), request.param("id"));
+        }
+
         updateRequest.routing(request.param("routing"));
         updateRequest.timeout(request.paramAsTime("timeout", updateRequest.timeout()));
         updateRequest.setRefreshPolicy(request.param("refresh"));

+ 50 - 0
server/src/test/java/org/elasticsearch/rest/action/document/RestUpdateActionTests.java

@@ -0,0 +1,50 @@
+/*
+ * 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.rest.action.document;
+
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.rest.RestRequest;
+import org.elasticsearch.rest.RestRequest.Method;
+import org.elasticsearch.test.rest.FakeRestRequest;
+import org.elasticsearch.test.rest.RestActionTestCase;
+import org.junit.Before;
+
+public class RestUpdateActionTests extends RestActionTestCase {
+
+    @Before
+    public void setUpAction() {
+        new RestUpdateAction(Settings.EMPTY, controller());
+    }
+
+    public void testTypeInPath() {
+        RestRequest deprecatedRequest = new FakeRestRequest.Builder(xContentRegistry())
+            .withMethod(Method.POST)
+            .withPath("/some_index/some_type/some_id/_update")
+            .build();
+        dispatchRequest(deprecatedRequest);
+        assertWarnings(RestUpdateAction.TYPES_DEPRECATION_MESSAGE);
+
+        RestRequest validRequest = new FakeRestRequest.Builder(xContentRegistry())
+            .withMethod(Method.POST)
+            .withPath("/some_index/_update/some_id")
+            .build();
+        dispatchRequest(validRequest);
+    }
+}