按查询升级

时间:2017-01-26 23:16:14

标签: elasticsearch

我正在尝试创建或更新我没有ID的文档。 所以我目前正在搜索/获取现有(或不是)文档,更新它并将其推回,并且它正在工作。

但是我想一下子就这么做。

我已经读过update by query看起来不适合这种情况的http://blah.com/1。 我也尝试过使用脚本,但只找到了更新的引用(所以我需要ID)。

不确定这是否可以在ES上使用。

非常感谢任何帮助/提示。

由于

更多信息:

在我的情况下,我与ID没有直接关系,这就是为什么我打算按查询更新

我的文件很简单:

{
  "text": "some text",
  "type": "a real type",
  "occurences": 2
}

所以我必须通过text和type键来匹配它。如果它不存在,则应添加一个新文档(出现为1),如果找到,则应将出现更新为3。

根据update_by_query的文档,应该可以执行以下操作:

POST /test/type/_update_by_query?conflicts=proceed
{
  "query": {
    "bool": {
      "must": [
         {"match_phrase": {"text": "some text"}},
         {"match_phrase": {"type": "a real type"}}
      ]
    }
  }
}

但我不知道该如何离开这里。

2 个答案:

答案 0 :(得分:1)

在使用动态生成的ID而不存储它们时,我偶然发现了确切的问题。

我认为在一个查询中无法执行,但您可以使用 _update_by_query 并检查响应正文以获取更新计数,如果为0,则可以安全地插入新实例。

所以在你的情况下,它会是这样的:

    POST /test/type/_update_by_query
    {
      "script": {
        "inline": "ctx._source.occurences++"
      },
      "query": {
        "bool": {
          "must": [
             {"match_phrase": {"text": "some text"}},
             {"match_phrase": {"type": "a real type"}}
          ]
        }
      }
    }

回应可能是:

  {
           "took": 2,
           "timed_out": false,
           "total": 0,
           "updated": 0,
           "deleted": 0,
           "batches": 0,
           "version_conflicts": 0,
           "noops": 0,
           "retries": {
              "bulk": 0,
              "search": 0
           },
           "throttled_millis": 0,
           "requests_per_second": -1,
           "throttled_until_millis": 0,
           "failures": []
 }

检查: if(response.updated == 0) 像这样。 True =>安全地插入新对象。 (也检查冲突)

POST /test/type/
{
  "text": "some text",
  "type": "a real type",
  "occurences": 1
}

ELSE不做任何事情,您的出现次数已更新。

使用此解决方案您可以最终获得竞争条件,您将获得version_conflicts。 如果你有这个问题,你可以做3件事。

  1. 使用queue和worker在请求后运行请求。
  2. 使用简单查询获取ID并使用可以指定数字的upsert 关于冲突和许多其他事情的重试。也可以选择批量更新。
  3. 使用以下选项:

    waitForCompletion:true,  冲突:"继续&#34 ;,  刷新:t​​rue

  4. 这将导致请求挂起,直到它被解决,因此响应时间将更长,它将等待完成并阻止。每个索引之后刷新也很糟糕,因为它会重新索引您的数据。这将导致更新版本,您将不再有版本冲突。

答案 1 :(得分:-1)

如果你看newest documentation,你应该能够做你想做的事。以下是文档中的示例:

POST twitter/_update_by_query
{
  "script": {
    "inline": "ctx._source.likes++",
    "lang": "painless"
  },
  "query": {
    "term": {
      "user": "kimchy"
    }
  }
}

此方法的缺点是您需要在群集上启用脚本。在生产中进行更改之前,您应该阅读有关此安全性和性能的含义。