使用脚本有条件地更新Elasticsearch

时间:2015-07-23 22:21:26

标签: 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
}'

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

任何其他方法建议也会受到高度赞赏。

2 个答案:

答案 0 :(得分:8)

Elasticsearch内置optimistic concurrency control+ herehere)。

它的工作方式是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
}'

此时文档的版本将为2,B的请求将以HTTP 409 Conflict结束,因为B假定文档仍处于版本1,即使版本在此期间增加由于A的要求。

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

答案 1 :(得分:2)

我认为脚本应该是这样的:

"script": "if(ctx._source.user_update_time > my_new_time) ctx._source.user_update_time=my_new_time;"

"script": "ctx._source.user_update_time > my_new_time ? ctx.op=\"none\" : ctx._source.user_update_time=my_new_time"