123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- [[docs-update]]
- === Update API
- ++++
- <titleabbrev>Update</titleabbrev>
- ++++
- Updates a document using the specified script.
- [[docs-update-api-request]]
- ==== {api-request-title}
- `POST /<index>/_update/<_id>`
- [[docs-update-api-prereqs]]
- ==== {api-prereq-title}
- * If the {es} {security-features} are enabled, you must have the `index` or
- `write` <<privileges-list-indices,index privilege>> for the target index or
- index alias.
- [[update-api-desc]]
- ==== {api-description-title}
- Enables you to script document updates. The script can update, delete, or skip
- modifying the document. The update API also supports passing a partial document,
- which is merged into the existing document. To fully replace an existing
- document, use the <<docs-index_,`index` API>>.
- This operation:
- . Gets the document (collocated with the shard) from the index.
- . Runs the specified script.
- . Indexes the result.
- The document must still be reindexed, but using `update` removes some network
- roundtrips and reduces chances of version conflicts between the GET and the
- index operation.
- The `_source` field must be enabled to use `update`. In addition to `_source`,
- you can access the following variables through the `ctx` map: `_index`,
- `_type`, `_id`, `_version`, `_routing`, and `_now` (the current timestamp).
- [[docs-update-api-path-params]]
- ==== {api-path-parms-title}
- `<index>`::
- (Required, string) Name of the target index. By default, the index is created
- automatically if it doesn't exist. For more information, see <<index-creation>>.
- `<_id>`::
- (Required, string) Unique identifier for the document to be updated.
- [[docs-update-api-query-params]]
- ==== {api-query-parms-title}
- include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=if_seq_no]
- include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=if_primary_term]
- `lang`::
- (Optional, string) The script language. Default: `painless`.
- include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=require-alias]
- include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=refresh]
- `retry_on_conflict`::
- (Optional, integer) Specify how many times should the operation be retried when
- a conflict occurs. Default: 0.
- include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=routing]
- `_source`::
- (Optional, list) Set to `false` to disable source retrieval (default: `true`).
- You can also specify a comma-separated list of the fields you want to retrieve.
- `_source_excludes`::
- (Optional, list) Specify the source fields you want to exclude.
- `_source_includes`::
- (Optional, list) Specify the source fields you want to retrieve.
- `timeout`::
- +
- --
- (Optional, <<time-units, time units>>)
- Period to wait for the following operations:
- * <<dynamic-mapping,Dynamic mapping>> updates
- * <<index-wait-for-active-shards,Waiting for active shards>>
- Defaults to `1m` (one minute). This guarantees {es} waits for at least the
- timeout before failing. The actual wait time could be longer, particularly when
- multiple waits occur.
- --
- include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=wait_for_active_shards]
- [[update-api-example]]
- ==== {api-examples-title}
- First, let's index a simple doc:
- [source,console]
- ----
- PUT test/_doc/1
- {
- "counter" : 1,
- "tags" : ["red"]
- }
- ----
- // TESTSETUP
- To increment the counter, you can submit an update request with the
- following script:
- [source,console]
- ----
- POST test/_update/1
- {
- "script" : {
- "source": "ctx._source.counter += params.count",
- "lang": "painless",
- "params" : {
- "count" : 4
- }
- }
- }
- ----
- Similarly, you could use and update script to add a tag to the list of tags
- (this is just a list, so the tag is added even it exists):
- [source,console]
- ----
- POST test/_update/1
- {
- "script": {
- "source": "ctx._source.tags.add(params.tag)",
- "lang": "painless",
- "params": {
- "tag": "blue"
- }
- }
- }
- ----
- You could also remove a tag from the list of tags. The Painless
- function to `remove` a tag takes the array index of the element
- you want to remove. To avoid a possible runtime error, you first need to
- make sure the tag exists. If the list contains duplicates of the tag, this
- script just removes one occurrence.
- [source,console]
- ----
- POST test/_update/1
- {
- "script": {
- "source": "if (ctx._source.tags.contains(params.tag)) { ctx._source.tags.remove(ctx._source.tags.indexOf(params.tag)) }",
- "lang": "painless",
- "params": {
- "tag": "blue"
- }
- }
- }
- ----
- You can also add and remove fields from a document. For example, this script
- adds the field `new_field`:
- [source,console]
- ----
- POST test/_update/1
- {
- "script" : "ctx._source.new_field = 'value_of_new_field'"
- }
- ----
- Conversely, this script removes the field `new_field`:
- [source,console]
- ----
- POST test/_update/1
- {
- "script" : "ctx._source.remove('new_field')"
- }
- ----
- // TEST[continued]
- The following script removes a subfield from an object field:
- ////
- [source,console]
- ----
- PUT test/_doc/1?refresh
- {
- "my-object": {
- "my-subfield": true
- }
- }
- ----
- ////
- [source,console]
- ----
- POST test/_update/1
- {
- "script": "ctx._source['my-object'].remove('my-subfield')"
- }
- ----
- // TEST[continued]
- Instead of updating the document, you can also change the operation that is
- executed from within the script. For example, this request deletes the doc if
- the `tags` field contains `green`, otherwise it does nothing (`noop`):
- [source,console]
- ----
- POST test/_update/1
- {
- "script": {
- "source": "if (ctx._source.tags.contains(params.tag)) { ctx.op = 'delete' } else { ctx.op = 'noop' }",
- "lang": "painless",
- "params": {
- "tag": "green"
- }
- }
- }
- ----
- [discrete]
- ===== Update part of a document
- The following partial update adds a new field to the
- existing document:
- [source,console]
- ----
- POST test/_update/1
- {
- "doc": {
- "name": "new_name"
- }
- }
- ----
- If both `doc` and `script` are specified, then `doc` is ignored. If you
- specify a scripted update, include the fields you want to update in the script.
- [discrete]
- ===== Detect noop updates
- By default updates that don't change anything detect that they don't change
- anything and return `"result": "noop"`:
- [source,console]
- ----
- POST test/_update/1
- {
- "doc": {
- "name": "new_name"
- }
- }
- ----
- // TEST[continued]
- If the value of `name` is already `new_name`, the update
- request is ignored and the `result` element in the response returns `noop`:
- [source,console-result]
- ----
- {
- "_shards": {
- "total": 0,
- "successful": 0,
- "failed": 0
- },
- "_index": "test",
- "_id": "1",
- "_version": 2,
- "_primary_term": 1,
- "_seq_no": 1,
- "result": "noop"
- }
- ----
- You can disable this behavior by setting `"detect_noop": false`:
- [source,console]
- ----
- POST test/_update/1
- {
- "doc": {
- "name": "new_name"
- },
- "detect_noop": false
- }
- ----
- [[upserts]]
- [discrete]
- ===== Upsert
- If the document does not already exist, the contents of the `upsert` element
- are inserted as a new document. If the document exists, the
- `script` is executed:
- [source,console]
- ----
- POST test/_update/1
- {
- "script": {
- "source": "ctx._source.counter += params.count",
- "lang": "painless",
- "params": {
- "count": 4
- }
- },
- "upsert": {
- "counter": 1
- }
- }
- ----
- [discrete]
- [[scripted_upsert]]
- ===== Scripted upsert
- To run the script whether or not the document exists, set `scripted_upsert` to
- `true`:
- [source,console]
- ----
- POST test/_update/1
- {
- "scripted_upsert": true,
- "script": {
- "source": """
- if ( ctx.op == 'create' ) {
- ctx._source.counter = params.count
- } else {
- ctx._source.counter += params.count
- }
- """,
- "params": {
- "count": 4
- }
- },
- "upsert": {}
- }
- ----
- [discrete]
- [[doc_as_upsert]]
- ===== Doc as upsert
- Instead of sending a partial `doc` plus an `upsert` doc, you can set
- `doc_as_upsert` to `true` to use the contents of `doc` as the `upsert`
- value:
- [source,console]
- ----
- POST test/_update/1
- {
- "doc": {
- "name": "new_name"
- },
- "doc_as_upsert": true
- }
- ----
- [NOTE]
- ====
- Using <<ingest,ingest pipelines>> with `doc_as_upsert` is not supported.
- ====
|