diff --git a/docs/reference/elasticsearch/rest-apis/update-document.md b/docs/reference/elasticsearch/rest-apis/update-document.md new file mode 100644 index 0000000000000..124d7fcc46fa9 --- /dev/null +++ b/docs/reference/elasticsearch/rest-apis/update-document.md @@ -0,0 +1,264 @@ +--- +mapped_pages: + - https://www.elastic.co/guide/en/elasticsearch/reference/8.18/docs-update.html +applies_to: + stack: all +navigation_title: Update a document +--- + +# Update a document [update-document] + +The [Update API](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-update) enables you to script document updates, allowing you to update, delete, or skip modifying a document. + +The following examples show common use cases, such as incrementing a counter and adding or removing elements from a list, as well as how to: + +- [Update part of a document](#update-part-document) +- [Detect noop updates](#detect-noop-updates) +- [Insert or update documents with upsert](#upsert) +- [Simplify upsert with doc_as_upsert](#doc-as-upsert) + +First, let's index a simple doc: + +```console +PUT test/_doc/1 +{ + "counter" : 1, + "tags" : ["red"] +} +``` +% TESTSETUP + +To increment the counter, you can submit an update request with the +following script: + +```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): + +```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. + +```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`: + +```console +POST test/_update/1 +{ + "script" : "ctx._source.new_field = 'value_of_new_field'" +} +``` + +Conversely, this script removes the field `new_field`: + +```console +POST test/_update/1 +{ + "script" : "ctx._source.remove('new_field')" +} +``` +% TEST[continued] + +The following script removes a subfield from an object field: + +```console +PUT test/_doc/1?refresh +{ + "my-object": { + "my-subfield": true + } +} +``` + +```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`): + +```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" + } + } +} +``` + +## Update part of a document [update-part-document] + +The following partial update adds a new field to the +existing document: + +```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. + + +## Detect noop updates [detect-noop-updates] + +By default updates that don't change anything detect that they don't change +anything and return `"result": "noop"`: + +```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`: + +```console + +{ + "_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`: + +```console +POST test/_update/1 +{ + "doc": { + "name": "new_name" + }, + "detect_noop": false +} +``` + +## Insert or update documents with upsert [upsert] + +An upsert operation lets you update an existing document or insert a new one if it doesn't exist, in a single request. + +In this example, if the product with ID `1` exists, its price will be updated to `100`. If the product does not exist, a new document with ID `1` and a price of `50` will be inserted. + +```console +POST /test/_update/1 +{ + "doc": { + "product_price": 100 + }, + "upsert": { + "product_price": 50 + } +} +``` + +## Run a scripted upsert [scripted-upsert] + +To run the script whether or not the document exists, set `scripted_upsert` to +`true`: + +```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": {} +} +``` + +## Simplify upsert with 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: + +```console +POST test/_update/1 +{ + "doc": { + "name": "new_name" + }, + "doc_as_upsert": true +} +``` + +::::{note} +Using [ingest pipelines](https://www.elastic.co/guide/en/elasticsearch/reference/8.18/ingest.html) with `doc_as_upsert` is not supported. +:::: diff --git a/docs/reference/elasticsearch/toc.yml b/docs/reference/elasticsearch/toc.yml index 16bffed9e0699..8b17179a12bc0 100644 --- a/docs/reference/elasticsearch/toc.yml +++ b/docs/reference/elasticsearch/toc.yml @@ -105,6 +105,7 @@ toc: - file: rest-apis/searching-with-query-rules.md - file: rest-apis/shard-request-cache.md - file: rest-apis/term-vectors-examples.md + - file: rest-apis/update-document.md - file: rest-apis/update-cc-api-key-examples.md - file: rest-apis/vector-tile-search.md - file: mapping-reference/index.md