update.asciidoc 8.8 KB

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