使用脚本有条件地更新Elasticsearch中的文档

bka*_*ler 8 groovy elasticsearch

我有一个用例,其中并发更新请求命中我的Elasticsearch集群.为了确保在较新的事件已经到达集群之后,陈旧事件(由较新的请求无关的事件)不更新文档,我想传递一个带有更新请求的脚本来比较字段确定传入请求是否相关.请求看起来像这样:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '
{
  "script": " IF ctx._source.user_update_time > my_new_time THEN do not update ELSE proceed with update",
  "params": {
    "my_new_time": "2014-09-01T17:36:17.517""
   },
  "doc": {
    "name": "new_name"
   },
  "doc_as_upsert": true
}'
Run Code Online (Sandbox Code Playgroud)

我在Elasticsearch的"脚本"字段中写的伪代码是可能的吗?如果是这样,我会喜欢一些语法帮助(groovy,python或javascript).

任何替代方法建议也将受到高度赞赏.

Val*_*Val 8

Elasticsearch具有内置的乐观并发控制(+此处此处).

它的工作方式是Update API允许您使用该version参数来控制更新是否应该继续.

因此,以上面的示例为例,第一个索引/更新操作将创建一个文档version: 1.然后假设您有两个并发请求.组件A和B都将发送更新的文档,它们最初都检索到文档,version: 1并将在其请求中指定该版本(请参阅version=1下面的查询字符串).当且仅当提供的版本与当前版本相同时, Elasticsearch才会更新文档

组件A和B都发送它,但是A的请求是第一个发出它的:

curl -XPOST 'localhost:9200/test/type1/1/_update?version=1' -d '{
  "doc": {
    "name": "new_name"
   },
  "doc_as_upsert": true
}'
Run Code Online (Sandbox Code Playgroud)

此时文档的版本将为2,B的请求将最终结束HTTP 409 Conflict,因为B假定文档仍处于版本1,即使版本因A的请求而同时增加.

B绝对可以使用新版本(即2)检索文档并再次尝试更新,但这次?version=2是在URL中.如果它是第一个到达ES的,则更新将成功.