ElasticSearch 6.3版本 Document APIs之Update API

Update API

Update API允许基于提供的脚本更新文档。该操作从索引获取文档(与分片并置),运行脚本(使用可选的脚本语言和参数),并对结果进行索引(也允许删除或忽略操作)。它使用版本控制来确保在“get”和“reindex”期间没有发生更新。

注意,此操作仍然意味着文档的完全重新索引,它指示删除了一些网络往返,并减少了get和索引之间版本冲突的可能性。_source需要启用该字段才能使此功能正常工作。

e.g.索引一个简单的文档:

PUT test/_doc/1
{
    "counter" : 1,
    "tags" : ["red"]
}

脚本更新

现在,执行一个增加计数器的脚本:
POST test/_doc/1/_update
{
    "script" : {
        "source": "ctx._source.counter += params.count",
        "lang": "painless",
        "params" : {
            "count" : 4
        }
    }
}
可以在标签列表中添加一个标签(如果标签存在,它仍会添加它,因为它是一个列表):
POST test/_doc/1/_update
{
    "script" : {
        "source": "ctx._source.tags.add(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')"
}
而且,我们甚至可以改变执行的操作。如果tags字段包含green,此示例将删除doc,否则它不执行任何操作(noop):

POST test/_doc/1/_update
{
    "script" : {
        "source": "if (ctx._source.tags.contains(params.tag)) { ctx.op = 'delete' } else { ctx.op = 'none' }",
        "lang": "painless",
        "params" : {
            "tag" : "green"
        }
    }
}
响应结果如下:

{
  "_index": "test",
  "_type": "_doc",
  "_id": "1",
  "_version": 12,
  "result": "noop",
  "_shards": {
    "total": 0,
    "successful": 0,
    "failed": 0
  }
}
执行删除操作时,返回结果result为deleted。


部分文档更新

Update API还支持传递部分文档,该部分文档将合并到现有文档中(简单的递归合并,对象的内部合并,替换核心“键/值”和数组)。要完全替换现有文档,应使用index API。以下部分更新会向现有文档添加新字段:
POST test/_doc/1/_update
{
    "doc" : {
        "name" : "new_name"
    }
}

如果同时doc和script指定,然后doc被忽略。最好是将部分文档的字段对放在脚本本身中。

但在实际操作中,如果同时指定doc和script,则会报错:

"type": "action_request_validation_exception",

"reason": " can't provide both script and doc;"

官方文档(2018-07-11)有误。


检查noop更新

如果doc指定,则其值与现有值合并_source。默认情况下,不更改任何内容的更新会检测到它们没有更改任何内容并返回“result”:“noop”,

如下所示:
POST 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": 6,
   "result": "noop"
}
您可以通过设置“detect_noop”来禁用此行为:false,如下所示:
POST test/_doc/1/_update
{
    "doc" : {
        "name" : "new_name"
    },
    "detect_noop": false
}
区别:

禁用此行为后,不更改任何内容的更新也会返回updated并且文档版本号加1;

不禁用此行为,不更改任何内容的更新会返回noop并且文档版本号不变。


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

如果无论文档是否存在您都希望脚本运行,即脚本处理初始化文档而不是upsert元素,设置scripted_upsert为true:

POST test/_doc/3/_update
{
  "scripted_upsert":true,
  "script":{
    "source":"ctx._source.counter += params.count",
    "lang": "painless",
    "params": {
      "count":4
    }
  },
  "upsert":{
    "counter":1
  }
}
注意:设置“scripted_upsert”为true后,如果文档3不存在,则会先创建文档3,将upsert元素的内容插入文档3,然后运行脚本script内容,即上述代码响应结果为(文档3起先并不存在):
{
  "_index": "test",
  "_type": "_doc",
  "_id": "3",
  "_version": 4,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 2,
    "failed": 0
  },
  "_seq_no": 3,
  "_primary_term": 1
}
查询文档3:GET test/_doc/3

响应结果为:

{
  "_index": "test",
  "_type": "_doc",
  "_id": "3",
  "_version": 1,
  "found": true,
  "_source": {
    "counter": 5
  }
}
doc_as_upsert

同scripted_upsert,如果无论文档是否存在您都希望脚本运行,即脚本处理初始化文档而不是upsert元素,设置doc_as_upsert为true(文档4不存在):

POST test/_doc/4/_update
{
  "doc":{
    "name":"doc_name"
  },
  "doc_as_upsert":true,
  "upsert":{
    "name":"upsert_name"
  }
}
上述代码响应结果为:
{
  "_index": "test",
  "_type": "_doc",
  "_id": "4",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 2,
    "failed": 0
  },
  "_seq_no": 42,
  "_primary_term": 1
}
查看文档4:GET test/_doc/4

响应结果:

{
  "_index": "test",
  "_type": "_doc",
  "_id": "4",
  "_version": 1,
  "found": true,
  "_source": {
    "name": "doc_name"
  }
}
如果没有doc_as_upsert为true这个设置,则文档4的内容为“upsert_name”。


参数编辑

更新操作支持以下查询字符串参数:

retry_on_conflict

在更新的get和indexing阶段之间,另一个进程可能已经更新了同一文档。默认情况下,更新将因版本冲突异常而失败。该retry_on_conflict 参数控制在最终抛出异常之前重试更新的次数。

routing

路由用于将更新请求路由到正确的分片,并在更新的文档不存在时为upsert请求设置路由。不能用于更新现有文档的路由。

timeout

超时等待碎片变为可用。

wait_for_active_shards

在继续更新操作之前需要处于活动状态的分片副本数。详情请见此处。

refresh

控制何时此请求所做的更改对搜索可见。见 ?refresh。

_source

允许控制是否以及如何在响应中返回更新的源。默认情况下,不会返回更新的源。详情source filtering请见。

version

更新API在内部使用Elasticsearch的版本控制支持,以确保在更新期间文档不会更改。您可以使用该version 参数指定仅在文档版本与指定版本匹配时才更新文档。

注意:更新API不支持内部版本以外的版本控制

更新API不支持外部(版本类型external&external_gte)或强制(版本类型force)版本控制,因为它会导致Elasticsearch版本号与外部系统不同步。请改用 indexAPI。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值