更新 API 允许基于脚本文件来更新文件。操作允许从索引中获取文件(并行的分片)来运行脚本文件(带有可选择的脚本语言和参数),最终索引获得结果(允许删除和忽略该操作)。它使用版本控制,以便于确保在获取和重索引时候没有更新发生。
注意,此操作仍然意味着对文件做重新的全索引。它只是删除了一些网络往返,减少了在索引和获取时候版本冲突的几率。 _source
需要启用此功能工作。
例如:一个简单的索引文件:
PUT test/type1/1
{
"counter" : 1,
"tags" : ["red"]
}
现在,我们可以执行一个脚本,用做计数器:
POST test/type1/1/_update
{
"script" : {
"inline": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
}
}
我们可以添加标签来进行标记(注意,如果标签存在,仍然会添加,因为是一个列表)
POST test/type1/1/_update
{
"script" : {
"inline": "ctx._source.tags.add(params.tag)",
"lang": "painless",
"params" : {
"tag" : "blue"
}
}
}
除了_source
,下列变量通过 ctx map 都是可用的
:_index
,_type
,_id
,_version
,_routing
,_parent
,和_now
(当前的时间戳)。
我们也可以将新字段添加到文档:
POST test/type1/1/_update
{
"script" : "ctx._source.new_field = \"value_of_new_field\""
}
或者从文件中删除字段:
POST test/type1/1/_update
{
"script" : "ctx._source.remove(\"new_field\")"
}
而且,我们甚至可以改变已执行的操作。这个例子就是删除文档,如果 tags
包含 green
,否则就什么也不做(noop
):
POST test/type1/1/_update
{
"script" : {
"inline": "if (ctx._source.tags.contains(params.tag)) { ctx.op = \"delete\" } else { ctx.op = \"none\" }",
"lang": "painless",
"params" : {
"tag" : "green"
}
}
}
更新 API 还支持部分文档的更新,将合并到现有的文件(简单的递归合并,内合并,更换核心“键/值”对和数组)。例如:
POST test/type1/1/_update
{
"doc" : {
"name" : "new_name"
}
}
如果同时 doc 和
script 被
指定,那么 doc
将被忽略。最好是把部分文件对应脚本本身。
检测空操作更新
如果 doc
指定,它的值合并到现有的 _source
。默认情况下不改变任何检测,他们不会改变任何并返回“结果”:“NOOP” 像这样的:
POST test/type1/1/_update
{
"doc" : {
"name" : "new_name"
}
}
如果 name
是 new_name
请求,被发送之前那么整个更新请求被忽略。如果请求被忽略了在 result
响应中的返回 noop。
{
"_shards": {
"total": 0,
"successful": 0,
"failed": 0
},
"_index": "test",
"_type": "type1",
"_id": "1",
"_version": 6,
"result": noop
}
你可以通过设置 “detect_noop” 禁用此行为:
POST test/type1/1/_update
{
"doc" : {
"name" : "new_name"
},
"detect_noop": true
}
如果该文件不存在,则内容upsert
元素将被插入作为一个新的文档。如果该文件确实存在,那么 script
将转而执行:
POST test/type1/1/_update
{
"script" : {
"inline": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
},
"upsert" : {
"counter" : 1
}
}
scripted_upsert
如果你想你的脚本无论该文件存在与否都要运行-即脚本处理初始化文件而不是 upsert -
然后设置 scripted_upsert
为 true:
POST sessions/session/dh3sgudg8gsrgl/_update
{
"scripted_upsert":true,
"script" : {
"id": "my_web_session_summariser",
"params" : {
"pageViewEvent" : {
"url":"foo.com/bar",
"response":404,
"time":"2014-01-01 12:32"
}
}
},
"upsert" : {}
}
doc_as_upsert
取代发送部分 doc 添加一个 ``upsert
文档,设置 doc_as_upsert
为 true ,
将使用 doc 内容
作为 upsert
值:
POST test/type1/1/_update
{
"doc" : {
"name" : "new_name"
},
"doc_as_upsert" : true
}
更新操作支持以下查询字符串参数:
retry_on_conflict | 在更新的 get 和 index 时,它可能是另一种方法可能已经更新了相同的文件。默认情况下,更新将失败,版本冲突异常。该 retry_on_conflict 参数控制抛出异常之前重试更新的次数。 |
routing | 用于追踪更新请求正确的分片,如果文档更新不存在把其设置为更新插入请求。不能用于更新现有文档的路径。 |
parent | 用于追踪更新请求正确的分片,如果文档更新不存在把 parent 设置为更新插入请求。不能用于更新 parent 现有文档的。如果被指定别名索引,那么它将覆盖父 route,它将用来 route 请求。 |
timeout | 超时等待一个分片变得可用。 |
wait_for_active_shards | 在更新操作时,复制分片需要处在活跃状态的数目。 |
refresh | 控制被该请求所做更改时进行的搜索。 |
_source | 允许控制是否以及更新源如何在响应中返回。默认情况下不返回更新的源。见 source_filtering 详情。 |
version &version_type |
更新 API 使用 Elasticsearch 的版本控制以确保文件在更新过程中不会改变。您可以使用 version 参数指定版本,如果文件匹配那么指定的文件需要更新。通过设置版本类型 force ,你可以更新后迫使文件使用新版本(小心使用!force 不会保证该文件没有变化)。 |