elasticsearch6.7 05. Document APIs(6)UPDATE API
5、 UPDATE API
更新操作可以使用脚本来更新。更新的时候会先从索引中获取文档数据(在每个分片中的集合),然后运行脚本(使用可选的脚本语言和参数),再果进行索引(还允许删除或忽略该操作)。它使用版本号保证在读取文档和重新索引期间,被更新的文档不会发生任何修改操作。
注意,update操作会重新索引文档,它可以减少网络往返次数和降低在获取文档和索引文档之间发生版本号冲突的可能。要支持这一特性,需要开启_source
字段(因为要读取旧数据,和替换操作不一样,替换操作不需要读旧数据).
例如,让我们索引一个简单的文档:
PUT test/type1/1
{
"counter" : 1,
"tags" : ["red"]
}
5.1 使用脚本更新(Scripted updates)
增加counter字段的值:
POST test/type1/1/_update
{
"script" : {
"inline": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
}
}
tags字段增加一个元素:
POST test/type1/1/_update
{
"script" : {
"inline": "ctx._source.tags.add(params.tag)",
"lang": "painless",
"params" : {
"tag" : "blue"
}
}
}
除了_source
,下面的变量是可用下面的字段都可以在ctx使用:_index
, _type
, _id
, _version
, _routing
, _parent
, and _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
就执行删除操作,否则什么都不做:
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"
}
}
}
5.1 脚本更新(Scripted updates)
现在执行一个增加计数器的脚本:
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"
}
}
}
可以从标签列表中删除标签。请注意,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' } else { ctx.op = 'none' }",
"lang": "painless",
"params" : {
"tag" : "green"
}
}
}
5.2 局部更新文档(Updates with a partial document)
update API 也支持将部分文档合并到现有文档中(简单的递归合并,对象的属性合并、替换属性值和数组)。要完全替换现有的文档,应使用 index API。以下的部分更新将向现有文档中添加新的字段:
POST test/_doc/1/_update
{
"doc" : {
"name" : "new_name"
}
}
如果doc
和script
一起指定,doc
将会被忽略。最好的更新方式是将部分文档的字段对放在脚本本身中。
5.3 检查空操作(Detecting noop updates)
如果指定了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": 7,
"result": "noop"
}
你可以通过设置 detect_noop
为false
来禁止 noop
,如:
POST test/_doc/1/_update
{
"doc" : {
"name" : "new_name"
},
"detect_noop": false
}
5.4 Upserts
如果文档不存在,就创建一个 与upsert
字段内容一致的文档,如果文档存在就执行script
中的更新操作:
POST test/_doc/1/_update
{
"script" : {
"source": "ctx._source.counter += params.count",
"lang": "painless",
"params" : {
"count" : 4
}
},
"upsert" : {
"counter" : 1
}
}
5.4.1 scripted_upsert
如果你想不管文档存不存在都要执行script
(即,用script
来初始化文档而不是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" : {}
}
5.4.2 doc_as_upsert
将doc_as_upsert
设置为true
,将会把 doc
中的值按照upsert
执行:
POST test/_doc/1/_update
{
"doc" : {
"name" : "new_name"
},
"doc_as_upsert" : true
}
5.5 参数(Parameters)
update操作支持如下查询参数:
- retry_on_conflict
- 在更新的get和indexing阶段之间,另一个进程可能已经更新了同一文档。默认情况下,更新会因版本冲突而失败。
retry_on_conflict
参数指定更新失败时重试多少次
- 在更新的get和indexing阶段之间,另一个进程可能已经更新了同一文档。默认情况下,更新会因版本冲突而失败。
- routing
- routing参数用于将更新请求路由到正确的分片。如果索引的时候指定了该参数,更新的时候也要指定同样的值。在使用
upsert
字段时,如果文档不存在的时候,就会创建新文档,此时可以指定这个文档的路由值。不能更新一个已存在的文档的routing
(就是说不能把文档从一个分片移动到另一个分片)。
- routing参数用于将更新请求路由到正确的分片。如果索引的时候指定了该参数,更新的时候也要指定同样的值。在使用
- timeout
- 等待分片变成可用状态的最大时间
- wait_for_active_shards
- 在执行更新操作前,至少有多少个可用的分片才能执行更新操作。详细请查阅
- refresh
- 控制此请求所做的更改何时对搜索可见。请查阅refresh
- _source
- 控制是否以及如何响应更新后的文档,默认不是会返回已更新的
_source
字段。查阅soruce filtering
- 控制是否以及如何响应更新后的文档,默认不是会返回已更新的
- version
- update API 使用 Elasticsearch 内部版本控制,以确保在更新期间文档不会被其他进程更新。你可以使用
version
参数指定仅在version和文档版本号一致时才更新文档。(在6.7.0中version以被弃用。请改用if_seq_no和if_primary_term,有关更多详细信息,请参阅乐观并发控制。)
- update API 使用 Elasticsearch 内部版本控制,以确保在更新期间文档不会被其他进程更新。你可以使用
update API不支持内部版本以外的版本控制
update API 不支持外部(
external
和external_gte
版本类型)或强制(force
版本类型)版本控制,这会导致 Elasticsearch 版本号与外部系统不同步。(比如外部版本号可以为0,但是内部版本号不可以为0)。你可以使用indexAPI 代替这个操作。
if_seq_no
和if_primary_term
- 更新操作可以是有条件的,只有在为文档的最后一次修改分配了if_seq_no和if_primary_term参数指定的序列号和主要术语时才能执行。如果检测到不匹配,则操作将导致VersionConflictException和状态代码409.有关详细信息,请参阅乐观并发控制。
elasticsearch6.7 05. Document APIs(6)UPDATE API的更多相关文章
- elasticsearch6.7 05. Document APIs(3)GET API
2.GET API get API 可以通过文档id从索引中获取json格式的文档,以下示例从twitter索引中获取type为_doc,id值为0为的JSON文档: GET twitter/_doc ...
- elasticsearch6.7 05. Document APIs(2)Index API
Single document APIs Index API Get API Delete API Update API Multi-document APIs Multi Get API Bulk ...
- elasticsearch6.7 05. Document APIs(9)Bulk API
8.Bulk API 可以把多个index或delete操作放在单个bulk API中执行.这样可以极大地提高索引速度. /_bulkAPI使用如下的JSON结构: action_and_meta_d ...
- elasticsearch6.7 05. Document APIs(7)Update By Query API
6.Update By Query API _update_by_query 接口可以在不改变 source 的情况下对 index 中的每个文档进行更新.这对于获取新属性或其他联机映射更改很有用.以 ...
- elasticsearch6.7 05. Document APIs(4)Delete API
3.Delete API delete API 可以让你删除一个特定id的文档,下面例子删除twitter索引中_doc类型.id为1的文档: DELETE /twitter/_doc/1 返回结果: ...
- elasticsearch6.7 05. Document APIs(10)Reindex API
9.REINDEX API Reindex要求为源索引中的所有文档启用_source. reindex 不会配置目标索引,不会复制源索引的设置.你需要在reindex之前先指定mapping,分片数量 ...
- elasticsearch6.7 05. Document APIs(5)Delete By Query API
4.Delete By Query API _delete_by_query API可以删除某个匹配条件的文档: POST twitter/_delete_by_query { "query ...
- elasticsearch6.7 05. Document APIs(8)Multi Get API
7.Multi Get API(Multi Get API) multi GET API 允许你一次性获取多个文档,你需要指定docs数组,其中包含了所有你需要查询的文档,每个查询结构至少包含索引,类 ...
- elasticsearch6.7 05. Document APIs(1)data replication model
data replication model 本节首先简要介绍Elasticsearch的data replication model,然后详细描述以下CRUD api: 1.读写文档(Reading ...
随机推荐
- Codeforces Round #512 (Div. 2) D. Vasya and Triangle
参考了别人的思路:https://blog.csdn.net/qq_41608020/article/details/82827632 http://www.cnblogs.com/qywhy/p/9 ...
- fork()函数、进程表示符、进程位置
linux.centos6.5 fork()函数:作用于创建子进程.返回值有两个,一个是向父进程返回它的pid,一个是返回0: eg1: #include<stdio.h> #includ ...
- Delphi fmx控件在手机滑动与单击的问题
Delphi fmx控件在手机滑动与单击的问题 (2016-03-08 10:52:00) 转载▼ 标签: it delphi 分类: Delphi10 众所周知,fmx制作的app,对于象TEdit ...
- 《Pro git》
可以通过阅读 CODING 工程师参与翻译的 <Pro Git> 进一步掌握 Git 版本控制系统. https://git-scm.com/book/zh/v2
- 浅谈ESB中的DataRow、DataSet、DataBag 、DataBox
1 背景概述 笔者在学习公司产品AEAI ESB 的时候经常需要从数据库获取信息并将数据信息保存到一个结果变量中,为统计分析提供特定格式的数据以及跨数据库同步数据时通常会用到DataRow.DataS ...
- kaldi脚本注释一
utils/split_data.sh ##再$data文件夹下,创建split{num_split}文件夹,再split×里面创建所有的数字文件夹#后面基本上是把$data文件夹下的各个文件都进行s ...
- MFS 服务扫描与爆破
MSF 服务发现 常用来发现局域网内,的常见服务,比如HTTP,FTP,TELNET等. MSF模块搜索: [root@localhost ~]# msfconsole msf5 > searc ...
- php 从2维数组组合为四维数组分析(项目中前台侧边栏导航三级分类显示)
foreach函数(循环函数)内嵌套循环函数时,当内层完全循环完后,才会向上一级循环 数组要注意问题 array_merge----合并一个或多个数组 将一个或多个数组的单元合并起来,一个数组中的值附 ...
- Java 中的 HttpServletRequest 和 HttpServletResponse 对象
HttpServletRequest对象详解 javax.servlet.http.HttpServletRequest是SUN制定的Servlet规范,是一个接口.表示请求,“HTTP请求协议”的完 ...
- 初识The ONE
Author:bakari Date:2014.1.14 转载请注出处:http://www.cnblogs.com/bakari/p/3519841.html,谢谢! 本学期开始做真正意义上的研究 ...