elasticsearch版本:6.5
更新API允许根据提供的脚本更新文档。该操作从索引中获取文档(在每个分片中的集合),运行脚本(使用可选的脚本语言和参数),并对结果进行索引(还允许删除或忽略该操作)。它使用版本控制来确保在“get”和“reindex”期间没有发生任何更新。
注意,此操作仍然意味着文档的完全reindex,它只是减少了一些网络传输,并减少get和索引之间版本冲突的可能性。需要启用_source字段才能使此功能正常工作。
例如,让我们索引一个简单的文档:
PUT test/_doc/1
{
"counter":1,
"tags":["red"]
}
(1)Scripted updates
下面的请求将增加counter字段的值:
POST test/_doc/1/_update
{
"script":{
"source":"ctx._source.counter += params.count",
"lang":"painless",
"params":{
"count":4
}
}
}
下面增加 一个tag到tags:
POST test/_doc/1/_update
{
"script":{
"source":"ctx._source.tags.add(params.tag)",
"lang":"painless",
"params":{
"tag":"blue"
}
}
}
下面可以移除tags里面的tag,注意painless的remove函数是需要你删除的tag的index,因此你需要想办法获取它来避免运行时出错。注意:如果要删除的tag在tags里面出现多次,但是只会删除一次。
POST test/_doc/1/_update
{
"script":{
"source":"if (ctx._source.tags.contains(params.tag)){ctx._source.tags.remove(ctx._source.tags.indexof(params.tag))}",
"lang":"painless",
"params":{
"tag":"blue"
}
}
}
除了_source,ctx的下面这些值也可以用:_index,_type,_id,_version,_routing和_now。
我们也可以这样添加一个字段:
POST test/_doc/1/_update
{
"script":"ctx._source.new_field = 'value_of_new_field'"
}
或是这样删除一个字段:
POST test/_doc/1/_update
{
"script":"ctx._source.remove('new_field')"
}
我们甚至可以指定ctx的操作,如下,判断tags是否包含green,如果包含则删除文档,否则不进行任何操作:
POST test/_doc/1/_update
{
"script":{
"source":"if(ctx._source.tags.contains(params.tag)) {ctx.op='delete'}",
"lang":"painless",
"params":{
"tags":"green"
}
}
}
(2)Updates with a partial document
update API也支持将部分文档合并到现有文档中(简单的递归合并,对象的属性合并、替换属性值和数组)。要完全替换现有的文档,应使用index API。一下的部分更新将向现有文档中添加新的字段:
POST test/_doc/1/_update
{
"doc":{
"name":"new_name"
}
}
如何both和script同时存在,那么doc将会被忽略。
(3)Detecting noop updates
如果指定了doc,则其值将与现有的_source合并。默认情况下,不更改任何内容的更新会检测到它们不更改任何内容并返回“result”:“noop”如下:
PUT test/_doc/1/_update
{
"doc":{
"name":"new _name"
}
}
如何name在更新前就是new_name,那么这个请求将会被忽略。返回值result的值将是noop:
{
"_shards": {
"total": 0,
"successful": 0,
"failed": 0
},
"_index": "test",
"_type": "_doc",
"_id": "1",
"_version": 7,
"result": "noop"
}
您可以禁止noop通过设置detect_noop为false,如:
POST test/_doc/1/_update
{
"doc" : {
"name" : "new_name"
},
"detect_noop": false
}
Upserts
如何文档不存在,upsert的内容将会创建一个新的文档,如果文件已经存在,就执行script中的更新内容:
POST test/_doc/1/_update
{
"script" : {
"source": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
},
"upsert" : {
"counter" : 1
}
}
scripted_upsert
如何您想只是script不管文档是否存在,那么设置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_as_upsert设置为true,将会把doc中的值按照upsert执行:
POST test/_doc/1/_update
{
"doc" : {
"name" : "new_name"
},
"doc_as_upsert" : true
}