2013-08-29 07:24:34 +08:00
|
|
|
[[docs-update]]
|
|
|
|
== Update API
|
|
|
|
|
|
|
|
The update API allows to update a document based on a script provided.
|
|
|
|
The operation gets the document (collocated with the shard) from the
|
|
|
|
index, runs the script (with optional script language and parameters),
|
|
|
|
and index back the result (also allows to delete, or ignore the
|
|
|
|
operation). It uses versioning to make sure no updates have happened
|
2013-09-04 03:27:49 +08:00
|
|
|
during the "get" and "reindex".
|
2013-08-29 07:24:34 +08:00
|
|
|
|
|
|
|
Note, this operation still means full reindex of the document, it just
|
|
|
|
removes some network roundtrips and reduces chances of version conflicts
|
|
|
|
between the get and the index. The `_source` field need to be enabled
|
|
|
|
for this feature to work.
|
|
|
|
|
|
|
|
For example, lets index a simple doc:
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
curl -XPUT localhost:9200/test/type1/1 -d '{
|
|
|
|
"counter" : 1,
|
|
|
|
"tags" : ["red"]
|
|
|
|
}'
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
Now, we can execute a script that would increment the counter:
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
|
|
|
|
"script" : "ctx._source.counter += count",
|
|
|
|
"params" : {
|
|
|
|
"count" : 4
|
|
|
|
}
|
|
|
|
}'
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
We can also add a tag to the list of tags (note, if the tag exists, it
|
|
|
|
will still add it, since its a list):
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
|
|
|
|
"script" : "ctx._source.tags += tag",
|
|
|
|
"params" : {
|
|
|
|
"tag" : "blue"
|
|
|
|
}
|
|
|
|
}'
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
We can also add a new field to the document:
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
|
|
|
|
"script" : "ctx._source.text = \"some text\""
|
|
|
|
}'
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
We can also remove a field from the document:
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
|
|
|
|
"script" : "ctx._source.remove(\"text\")"
|
|
|
|
}'
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
And, we can delete the doc if the tags contain blue, or ignore (noop):
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
|
|
|
|
"script" : "ctx._source.tags.contains(tag) ? ctx.op = \"delete\" : ctx.op = \"none\"",
|
|
|
|
"params" : {
|
|
|
|
"tag" : "blue"
|
|
|
|
}
|
|
|
|
}'
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
*Note*: Be aware of MVEL and handling of ternary operators and
|
|
|
|
assignments. Assignment operations have lower precedence than the
|
|
|
|
ternary operator. Compare the following statements:
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
// Will NOT update the tags array
|
|
|
|
ctx._source.tags.contains(tag) ? ctx.op = \"none\" : ctx._source.tags += tag
|
|
|
|
// Will update
|
|
|
|
ctx._source.tags.contains(tag) ? (ctx.op = \"none\") : ctx._source.tags += tag
|
|
|
|
// Also works
|
|
|
|
if (ctx._source.tags.contains(tag)) { ctx.op = \"none\" } else { ctx._source.tags += tag }
|
|
|
|
--------------------------------------------------
|
|
|
|
|
2013-09-04 03:27:49 +08:00
|
|
|
The update API also support passing a partial document,
|
2013-08-29 07:24:34 +08:00
|
|
|
which will be merged into the existing document (simple recursive merge,
|
|
|
|
inner merging of objects, replacing core "keys/values" and arrays). For
|
|
|
|
example:
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
|
|
|
|
"doc" : {
|
|
|
|
"name" : "new_name"
|
|
|
|
}
|
|
|
|
}'
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
If both `doc` and `script` is specified, then `doc` is ignored. Best is
|
|
|
|
to put your field pairs of the partial document in the script itself.
|
|
|
|
|
2014-07-15 00:43:29 +08:00
|
|
|
By default if `doc` is specified then the document is always updated even
|
|
|
|
if the merging process doesn't cause any changes. Specifying `detect_noop`
|
|
|
|
as `true` will cause Elasticsearch to check if there are changes and, if
|
|
|
|
there aren't, turn the update request into a noop. For example:
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
|
|
|
|
"doc" : {
|
|
|
|
"name" : "new_name"
|
|
|
|
},
|
|
|
|
"detect_noop": true
|
|
|
|
}'
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
If `name` was `new_name` before the request was sent then the entire update
|
|
|
|
request is ignored.
|
|
|
|
|
2013-09-04 03:27:49 +08:00
|
|
|
There is also support for `upsert`. If the document does
|
2013-08-29 07:24:34 +08:00
|
|
|
not already exists, the content of the `upsert` element will be used to
|
|
|
|
index the fresh doc:
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
|
|
|
|
"script" : "ctx._source.counter += count",
|
|
|
|
"params" : {
|
|
|
|
"count" : 4
|
|
|
|
},
|
|
|
|
"upsert" : {
|
|
|
|
"counter" : 1
|
|
|
|
}
|
|
|
|
}'
|
|
|
|
--------------------------------------------------
|
|
|
|
|
2013-09-04 03:27:49 +08:00
|
|
|
Last it also supports `doc_as_upsert`. So that the
|
2013-08-29 07:24:34 +08:00
|
|
|
provided document will be inserted if the document does not already
|
|
|
|
exist. This will reduce the amount of data that needs to be sent to
|
|
|
|
elasticsearch.
|
|
|
|
|
|
|
|
[source,js]
|
|
|
|
--------------------------------------------------
|
|
|
|
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
|
|
|
|
"doc" : {
|
|
|
|
"name" : "new_name"
|
|
|
|
},
|
|
|
|
"doc_as_upsert" : true
|
|
|
|
}'
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
The update operation supports similar parameters as the index API,
|
|
|
|
including:
|
|
|
|
|
|
|
|
[horizontal]
|
|
|
|
`routing`:: Sets the routing that will be used to route the
|
|
|
|
document to the relevant shard.
|
|
|
|
|
|
|
|
`parent`:: Simply sets the routing.
|
|
|
|
|
|
|
|
`timeout`:: Timeout waiting for a shard to become available.
|
|
|
|
|
|
|
|
`replication`:: The replication type for the delete/index operation
|
|
|
|
(sync or async).
|
|
|
|
|
|
|
|
`consistency`:: The write consistency of the index/delete operation.
|
|
|
|
|
|
|
|
`refresh`:: Refresh the index immediately after the operation occurs,
|
|
|
|
so that the updated document appears in search results
|
|
|
|
immediately.
|
|
|
|
|
2013-09-04 03:27:49 +08:00
|
|
|
`fields`:: return the relevant fields from the updated document.
|
|
|
|
Support `_source` to return the full updated
|
2013-08-29 07:24:34 +08:00
|
|
|
source.
|
|
|
|
|
2014-04-23 17:13:25 +08:00
|
|
|
`version` & `version_type`:: the Update API uses the Elasticsearch's versioning
|
|
|
|
support internally to make sure the document doesn't change
|
|
|
|
during the update. You can use the `version` parameter to specify that the
|
|
|
|
document should only be updated if it's version matches the one specified.
|
|
|
|
By setting version type to `force` you can force the new version of the document
|
|
|
|
after update (use with care! with `force` there is no guaranty the document
|
|
|
|
didn't change).Version types `external` & `external_gte` are not supported.
|
|
|
|
|
2013-08-29 07:24:34 +08:00
|
|
|
|
|
|
|
And also support `retry_on_conflict` which controls how many times to
|
|
|
|
retry if there is a version conflict between getting the document and
|
|
|
|
indexing / deleting it. Defaults to `0`.
|
|
|
|
|
|
|
|
It also allows to update the `ttl` of a document using `ctx._ttl` and
|
|
|
|
timestamp using `ctx._timestamp`. Note that if the timestamp is not
|
|
|
|
updated and not extracted from the `_source` it will be set to the
|
|
|
|
update date.
|