前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >ElasticSearch API 之 UPDATE

ElasticSearch API 之 UPDATE

作者头像
leehao
发布2025-02-11 13:05:38
发布2025-02-11 13:05:38
9300
代码可运行
举报
文章被收录于专栏:leehao
运行总次数:0
代码可运行

ES本身是一个倾向于查询检索的框架,对于更新的操作,太过频繁总归不好的。 阅读本篇后,你可以使用Script对所有的文档执行更新操作,也可以使用doc对部分文档执行更新,也可以使用upsert对不存在的文档执行添加操作。 参考:http://www.cnblogs.com/xing901022/p/5330778.html

更新

更新操作允许ES获得某个指定的文档,可以通过脚本等操作对该文档进行更新。

可以把它看成是先删除再索引的原子操作,只是省略了返回的过程,这样即节省了来回传输的网络流量,也避免了中间时间造成的文档修改冲突。

下面例子,查找id为25的文档:

代码语言:javascript
代码运行次数:0
复制
curl -XGET localhost:9200/bank/account/25?pretty{
 
 "_index": "bank","_type": "account","_id": "25","_version": 1,"found": true,"_source": {
   
   "account_number": 25,"balance": 40540,"firstname": "Virginia","lastname": "Ayala","age": 39,"gender": "F","address": "171 Putnam Avenue","employer": "Filodyne","email": "virginiaayala@filodyne.com","city": "Nicholson","state": "PA"}}

脚本更新

Es支持通过脚本更改文档的信息:

代码语言:javascript
代码运行次数:0
复制
curl -XPOST 'localhost:9200/bank/account/25/_update' -d '{
    "script" : {
        "inline": "ctx._source.age += number",
        "params" : {
            "number" : 5
        }
    }
}'结果报错:{
 
 "error": {
   
   "root_cause": [
     
     { 
       "type": "remote_transport_exception","reason": "[lihao][127.0.0.1:9300][indices:data/write/update[s]]"}],"type": "illegal_argument_exception","reason": "failed to execute script","caused_by": {
     
     "type": "script_exception","reason": "scripts of type [inline], operation [update] and lang [groovy] are disabled"}},"status": 400}
报错原因:  在最新版本的Elasticsearch中,基于安全考虑(如果用不到,请保持禁用),默认禁用了动态脚本功能。完全开启动态脚本功能
script.inline: on
script.indexed: on
script.file: on  重启ES
{
 
 "_index": "bank","_type": "account","_id": "25","_version": 2,"_shards": {
   
   "total": 2,"successful": 1,"failed": 0}}
代码语言:javascript
代码运行次数:0
复制
curl -XGET localhost:9200/bank/account/25?pretty

{   "_index" : "bank",   "_type" : "account",   "_id" : "25",   "_version" : 2,   "found" : true,   "_source" : {     "account_number" : 25,     "balance" : 40540,     "firstname" : "Virginia",     "lastname" : "Ayala", "age" : 44,     "gender" : "F",     "address" : "171 Putnam Avenue",     "employer" : "Filodyne",     "email" : "virginiaayala@filodyne.com",     "city" : "Nicholson",     "state" : "PA"   } }

上面就是通过参数来为age加5.

除了_source字段,可以通过ctx来获得_index_type_id_version_parent_timestamp_ttl等字段信息。

也可以添加某个字段:

代码语言:javascript
代码运行次数:0
复制
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : "ctx._source.name_of_new_field = \"value_of_new_field\""
}'

移除字段:

代码语言:javascript
代码运行次数:0
复制
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : "ctx._source.remove(\"name_of_field\")"
}'

也支持稍微复杂点的操作,逻辑判断,比如根据某个标记执行不同的操作。比如如果有blue这个标记,则删除该文档;否则什么也不做:

代码语言:javascript
代码运行次数:0
复制
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : {
        "inline": "ctx._source.tags.contains(tag) ? ctx.op = \"delete\" : ctx.op = \"none\"",
        "params" : {
            "tag" : "blue"
        }
    }
}'

只更新部分文档

上面的脚本是对所有的文档都起作用,这里讲解下如何只对部分文档进行修改。使用doc可以实现简单的递归合并、内部合并、替换KV以及数组。

代码语言:javascript
代码运行次数:0
复制
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "doc" : {
        "name" : "new_name"
    }
}'

如果同时使用了doc和script,那么doc的操作会自动忽略。因此最好是把特殊的操作也放在脚本中。

更新检测

如果使用doc,那么会自动合并到现有的文档中。如果doc中定义的部分与现在的文档相同,则默认不会执行任何动作。设置detect_noop=false,就会无视是否修改,强制合并到现有的文档。

代码语言:javascript
代码运行次数:0
复制
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "doc" : {
        "name" : "new_name"
    },
    "detect_noop": false
}'

上面的例子中,如果name字段为new_name,无论当前的文档是否与doc中定义的相同,都会把doc合并到文档中。

upsert插入

这个参数主要用于当文档不存在时,ES的操作。

代码语言:javascript
代码运行次数:0
复制
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "script" : {
        "inline": "ctx._source.counter += count",
        "params" : {
            "count" : 4
        }
    },
    "upsert" : {
        "counter" : 1
    }
}'

在上面的例子中,当文档存在时,执行脚本;当文档不存在时,upsert中的内容就会插入到对应的文档中。

如果你想无论文档是否存在都执行脚本操作,那么可以使用参数scripted_upsert为true。

代码语言:javascript
代码运行次数:0
复制
curl -XPOST 'localhost:9200/sessions/session/dh3sgudg8gsrgl/_update' -d '{
    "scripted_upsert":true,
    "script" : {
        "id": "my_web_session_summariser",
        "params" : {
            "pageViewEvent" : {
                "url":"foo.com/bar",
                "response":404,
                "time":"2014-01-01 12:32"
            }
        }
    },
    "upsert" : {}
}'

相对于之前的使用Upsert中的内容添加到不存在的文档,使用doc_as_upsert可以在文档不存在的时候,把doc中的内容插入到文档中。

代码语言:javascript
代码运行次数:0
复制
curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
    "doc" : {
        "name" : "new_name"
    },
    "doc_as_upsert" : true
}'
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-02-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 更新
  • 脚本更新
  • 只更新部分文档
  • 更新检测
  • upsert插入
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档