update.asciidoc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. [[docs-update]]
  2. === Update API
  3. ++++
  4. <titleabbrev>Update</titleabbrev>
  5. ++++
  6. Updates a document using the specified script.
  7. [[docs-update-api-request]]
  8. ==== {api-request-title}
  9. `POST /<index>/_update/<_id>`
  10. [[docs-update-api-prereqs]]
  11. ==== {api-prereq-title}
  12. * If the {es} {security-features} are enabled, you must have the `index` or
  13. `write` <<privileges-list-indices,index privilege>> for the target index or
  14. index alias.
  15. [[update-api-desc]]
  16. ==== {api-description-title}
  17. Enables you to script document updates. The script can update, delete, or skip
  18. modifying the document. The update API also supports passing a partial document,
  19. which is merged into the existing document. To fully replace an existing
  20. document, use the <<docs-index_,`index` API>>.
  21. This operation:
  22. . Gets the document (collocated with the shard) from the index.
  23. . Runs the specified script.
  24. . Indexes the result.
  25. The document must still be reindexed, but using `update` removes some network
  26. roundtrips and reduces chances of version conflicts between the GET and the
  27. index operation.
  28. The `_source` field must be enabled to use `update`. In addition to `_source`,
  29. you can access the following variables through the `ctx` map: `_index`,
  30. `_type`, `_id`, `_version`, `_routing`, and `_now` (the current timestamp).
  31. [[docs-update-api-path-params]]
  32. ==== {api-path-parms-title}
  33. `<index>`::
  34. (Required, string) Name of the target index. By default, the index is created
  35. automatically if it doesn't exist. For more information, see <<index-creation>>.
  36. `<_id>`::
  37. (Required, string) Unique identifier for the document to be updated.
  38. [[docs-update-api-query-params]]
  39. ==== {api-query-parms-title}
  40. include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=if_seq_no]
  41. include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=if_primary_term]
  42. `lang`::
  43. (Optional, string) The script language. Default: `painless`.
  44. include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=require-alias]
  45. include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=refresh]
  46. `retry_on_conflict`::
  47. (Optional, integer) Specify how many times should the operation be retried when
  48. a conflict occurs. Default: 0.
  49. include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=routing]
  50. `_source`::
  51. (Optional, list) Set to `false` to disable source retrieval (default: `true`).
  52. You can also specify a comma-separated list of the fields you want to retrieve.
  53. `_source_excludes`::
  54. (Optional, list) Specify the source fields you want to exclude.
  55. `_source_includes`::
  56. (Optional, list) Specify the source fields you want to retrieve.
  57. `timeout`::
  58. +
  59. --
  60. (Optional, <<time-units, time units>>)
  61. Period to wait for the following operations:
  62. * <<dynamic-mapping,Dynamic mapping>> updates
  63. * <<index-wait-for-active-shards,Waiting for active shards>>
  64. Defaults to `1m` (one minute). This guarantees {es} waits for at least the
  65. timeout before failing. The actual wait time could be longer, particularly when
  66. multiple waits occur.
  67. --
  68. include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=wait_for_active_shards]
  69. [[update-api-example]]
  70. ==== {api-examples-title}
  71. First, let's index a simple doc:
  72. [source,console]
  73. ----
  74. PUT test/_doc/1
  75. {
  76. "counter" : 1,
  77. "tags" : ["red"]
  78. }
  79. ----
  80. // TESTSETUP
  81. To increment the counter, you can submit an update request with the
  82. following script:
  83. [source,console]
  84. ----
  85. POST test/_update/1
  86. {
  87. "script" : {
  88. "source": "ctx._source.counter += params.count",
  89. "lang": "painless",
  90. "params" : {
  91. "count" : 4
  92. }
  93. }
  94. }
  95. ----
  96. Similarly, you could use and update script to add a tag to the list of tags
  97. (this is just a list, so the tag is added even it exists):
  98. [source,console]
  99. ----
  100. POST test/_update/1
  101. {
  102. "script": {
  103. "source": "ctx._source.tags.add(params.tag)",
  104. "lang": "painless",
  105. "params": {
  106. "tag": "blue"
  107. }
  108. }
  109. }
  110. ----
  111. You could also remove a tag from the list of tags. The Painless
  112. function to `remove` a tag takes the array index of the element
  113. you want to remove. To avoid a possible runtime error, you first need to
  114. make sure the tag exists. If the list contains duplicates of the tag, this
  115. script just removes one occurrence.
  116. [source,console]
  117. ----
  118. POST test/_update/1
  119. {
  120. "script": {
  121. "source": "if (ctx._source.tags.contains(params.tag)) { ctx._source.tags.remove(ctx._source.tags.indexOf(params.tag)) }",
  122. "lang": "painless",
  123. "params": {
  124. "tag": "blue"
  125. }
  126. }
  127. }
  128. ----
  129. You can also add and remove fields from a document. For example, this script
  130. adds the field `new_field`:
  131. [source,console]
  132. ----
  133. POST test/_update/1
  134. {
  135. "script" : "ctx._source.new_field = 'value_of_new_field'"
  136. }
  137. ----
  138. Conversely, this script removes the field `new_field`:
  139. [source,console]
  140. ----
  141. POST test/_update/1
  142. {
  143. "script" : "ctx._source.remove('new_field')"
  144. }
  145. ----
  146. // TEST[continued]
  147. The following script removes a subfield from an object field:
  148. ////
  149. [source,console]
  150. ----
  151. PUT test/_doc/1?refresh
  152. {
  153. "my-object": {
  154. "my-subfield": true
  155. }
  156. }
  157. ----
  158. ////
  159. [source,console]
  160. ----
  161. POST test/_update/1
  162. {
  163. "script": "ctx._source['my-object'].remove('my-subfield')"
  164. }
  165. ----
  166. // TEST[continued]
  167. Instead of updating the document, you can also change the operation that is
  168. executed from within the script. For example, this request deletes the doc if
  169. the `tags` field contains `green`, otherwise it does nothing (`noop`):
  170. [source,console]
  171. ----
  172. POST test/_update/1
  173. {
  174. "script": {
  175. "source": "if (ctx._source.tags.contains(params.tag)) { ctx.op = 'delete' } else { ctx.op = 'noop' }",
  176. "lang": "painless",
  177. "params": {
  178. "tag": "green"
  179. }
  180. }
  181. }
  182. ----
  183. [discrete]
  184. ===== Update part of a document
  185. The following partial update adds a new field to the
  186. existing document:
  187. [source,console]
  188. ----
  189. POST test/_update/1
  190. {
  191. "doc": {
  192. "name": "new_name"
  193. }
  194. }
  195. ----
  196. If both `doc` and `script` are specified, then `doc` is ignored. If you
  197. specify a scripted update, include the fields you want to update in the script.
  198. [discrete]
  199. ===== Detect noop updates
  200. By default updates that don't change anything detect that they don't change
  201. anything and return `"result": "noop"`:
  202. [source,console]
  203. ----
  204. POST test/_update/1
  205. {
  206. "doc": {
  207. "name": "new_name"
  208. }
  209. }
  210. ----
  211. // TEST[continued]
  212. If the value of `name` is already `new_name`, the update
  213. request is ignored and the `result` element in the response returns `noop`:
  214. [source,console-result]
  215. ----
  216. {
  217. "_shards": {
  218. "total": 0,
  219. "successful": 0,
  220. "failed": 0
  221. },
  222. "_index": "test",
  223. "_id": "1",
  224. "_version": 2,
  225. "_primary_term": 1,
  226. "_seq_no": 1,
  227. "result": "noop"
  228. }
  229. ----
  230. You can disable this behavior by setting `"detect_noop": false`:
  231. [source,console]
  232. ----
  233. POST test/_update/1
  234. {
  235. "doc": {
  236. "name": "new_name"
  237. },
  238. "detect_noop": false
  239. }
  240. ----
  241. [[upserts]]
  242. [discrete]
  243. ===== Upsert
  244. If the document does not already exist, the contents of the `upsert` element
  245. are inserted as a new document. If the document exists, the
  246. `script` is executed:
  247. [source,console]
  248. ----
  249. POST test/_update/1
  250. {
  251. "script": {
  252. "source": "ctx._source.counter += params.count",
  253. "lang": "painless",
  254. "params": {
  255. "count": 4
  256. }
  257. },
  258. "upsert": {
  259. "counter": 1
  260. }
  261. }
  262. ----
  263. [discrete]
  264. [[scripted_upsert]]
  265. ===== Scripted upsert
  266. To run the script whether or not the document exists, set `scripted_upsert` to
  267. `true`:
  268. [source,console]
  269. ----
  270. POST test/_update/1
  271. {
  272. "scripted_upsert": true,
  273. "script": {
  274. "source": """
  275. if ( ctx.op == 'create' ) {
  276. ctx._source.counter = params.count
  277. } else {
  278. ctx._source.counter += params.count
  279. }
  280. """,
  281. "params": {
  282. "count": 4
  283. }
  284. },
  285. "upsert": {}
  286. }
  287. ----
  288. [discrete]
  289. [[doc_as_upsert]]
  290. ===== Doc as upsert
  291. Instead of sending a partial `doc` plus an `upsert` doc, you can set
  292. `doc_as_upsert` to `true` to use the contents of `doc` as the `upsert`
  293. value:
  294. [source,console]
  295. ----
  296. POST test/_update/1
  297. {
  298. "doc": {
  299. "name": "new_name"
  300. },
  301. "doc_as_upsert": true
  302. }
  303. ----
  304. [NOTE]
  305. ====
  306. Using <<ingest,ingest pipelines>> with `doc_as_upsert` is not supported.
  307. ====