原文地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html
elasticsearch版本:6.5
目录地址:https://blog.csdn.net/mine_1/article/details/85623429
_update_by_query接口可以在不改变source的情况下在index中更新文档。这对于获取新属性或其他联机映射更改很有用。以下是API:
POST twitter/_update_by_query?conflicts=proceed
得到的影响为:
{
"took" : 147,
"timed_out": false,
"updated": 120,
"deleted": 0,
"batches": 1,
"version_conflicts": 0,
"noops": 0,
"retries": {
"bulk": 0,
"search": 0
},
"throttled_millis": 0,
"requests_per_second": -1.0,
"throttled_until_millis": 0,
"total": 120,
"failures" : [ ]
}
_update_by_query在开始执行的时候获得一个快照,并使用内部版本控制对找到的内容进行索引。这意味着,如果文档在获取快照和处理索引请求之间发生更改,则会出现版本冲突。当版本对应的文档发生改变成,对应的版本号也会增加。
所有的更新和查找失败都是导致_update_by_query中止并且在response中返回failures。已经更新的内容仍然存在。也就是说这个操作不会回滚,只会中止。当第一个错误引起中止后,所有的错误都会返回到failures元素中,因此有可能有相当多的失败实例。
如何您想在遇到版本冲突时继续执行_updata_by_query,那么可以在url中设置conflicts=proceed或是在请求中设置"conflicts":"proceed"。第一个例子这样设置,是因为它想要获得在线映射改变,版本冲突仅仅意味着冲突文档在_update_by_query的开始时间和试图更新文档的时间之间被更新。这没关系,因为该更新将获取联机映射更新。
下面的例子将会updata twitter index里面的tweets:
POST twitter/_doc/_update_by_query?conflicts=proceed
您也可以利用query语句限制更新,下面的例子将会更新所有user为kimchy的twitter:
POST twitter/_update_by_query?conflicts=proceed
{
"query":{
"term":{
"user":"kimchy"
}
}
}
目前,我们在更新文档的时候没有更改source。这对诸如获取新属性很有用,但只是其中一般的乐趣。_update_by_query支持用脚本来更新文档。下面的例子将会把kimchy的likes字段加1:
POST twitter/_update_by_query
{
"script":{
"source":"ctx._source.likes++",
"lang":"painless"
}
"query":{
"term":{
"user":"kimchy"
}
}
}
正如在更新API中一样,您可以设置ctx.op来更改执行的操作:
将ctx.op设置为其他值都是错误的,在ctx中设置其他字段也都是错误的。
注意,如果我们取消设置conflicts=proceed,在这种情况下,我们希望版本冲突能够中止进程以便于我们进行处理。
这个接口不允许您移动涉及到的文档,只能是修改它的source。这是故意设计的。我们没有想要将文件移动位置。
这个接口也可以一次修改多个indexes和多个类型,如:
POST twitter,blog/_doc,post/_update_by_query
如何设置了路由,那么操作的分片还应该满足路由的条件,如:
POST twitter/_update_by_query?routing=1
_update_by_query默认饿scroll batches是1000,您可以通过设置scroll_size修改此值:
POST twitter/_update_by_query?scroll_size=100
_update_by_query也可以用ingest接口pipeline,如:
PUT _ingest/pipeline/set-foo
{
"description" : "sets foo",
"processors" : [ {
"set" : {
"field": "foo",
"value": "bar"
}
} ]
}
POST twitter/_update_by_query?pipeline=set-foo
(1)URL Parameters
(2)响应体
{
"took" : 147,
"timed_out": false,
"total": 5,
"updated": 5,
"deleted": 0,
"batches": 1,
"version_conflicts": 0,
"noops": 0,
"retries": {
"bulk": 0,
"search": 0
},
"throttled_millis": 0,
"requests_per_second": -1.0,
"throttled_until_millis": 0,
"failures" : [ ]
}
(3)works with the task API
您可以利用task api获得正在运行的所有的update_by_query请求的状态:
GET _tasks?detailed=true&actions=*byquery
得到的响应为:
{
"nodes" : {
"r1A2WoRbTwKZ516z6NEs5A" : {
"name" : "r1A2WoR",
"transport_address" : "127.0.0.1:9300",
"host" : "127.0.0.1",
"ip" : "127.0.0.1:9300",
"attributes" : {
"testattr" : "test",
"portsfile" : "true"
},
"tasks" : {
"r1A2WoRbTwKZ516z6NEs5A:36619" : {
"node" : "r1A2WoRbTwKZ516z6NEs5A",
"id" : 36619,
"type" : "transport",
"action" : "indices:data/write/update/byquery",
"status" : {
"total" : 6154,
"updated" : 3500,
"created" : 0,
"deleted" : 0,
"batches" : 4,
"version_conflicts" : 0,
"noops" : 0,
"retries": {
"bulk": 0,
"search": 0
},
"throttled_millis": 0
},
"description" : ""
}
}
}
}
}
有了task id,您就可以直接查看指定的task的信息了:
GET /_tasks/r1A2WoRbTwKZ516z6NEs5A:36619
这个API结合wait_for_comletion=false设置一起便捷的提供正在运行的task的状态。如果task运行完成了或是设置wait_for_completion=true,那么就会返回错误信息。这个功能的代价是在.tasks/task/${taskId}目录下创建一个文档,你可以根据需要删除该文档。
(4)works with the cancel task API
_update_by_query操作可以利用如下接口取消:
POST _tasks/r1A2WoRbTwKZ516z6NEs5A:36619/_cancel
(5)rethrottling
requests_per_second参数可以通过如下方法进行修改:
POST _update_by_query/r1A2WoRbTwKZ516z6NEs5A:36619/_rethrottle?requests_per_second=-1
和requests_per_seconds参数设置一样,rethrottling参数只能是-1或是其他十进制数。rethrottling参数提高速度会立刻其作用,但是降低速度会等到当前操作执行完后起作用。
(6)Slicing
update_by_query支持sliced scroll来并行执行更新操作。这种并行化可以提高效率,并提供一种方便的方法来将请求分解为更小的部分来执行。
Manual Slicing
手动slice需要为每个请求提供一个slice id和每个slices的总的个数,如:
POST twitter/_update_by_query
{
"slice":{
"id":0,
"max":2
},
"script":{
"source":"ctx._source['extra'] = 'test'"
}
}
POST twitter/_update_by_query
{
"slice":{
"id":1,
"max":2
},
"script":{
"source":"ctx._source['extra'] = 'test'"
}
}
可以通过下列语句验证运行结果:
GET _refresh
POST twitter/_search?size=0&q=extra:test&filter_path=hits.total
得到的响应如下:
{
"hits":{
"total":120
}
}
Automatic slicing
您也可以让update_by_query自动sliced scroll,用slices参数设置slices的个数,如:
POST twitter/_update_by_query?refresh&slices=5
{
"script":{
"source":"ctx._source['extra'] = 'test'"
}
}
您可以通过下列语句验证运行结果:
POST twitter/_search?size=0&q=extra:test&filter_path=hits.total
得到的响应如下:
{
"hits":{
"total":120
}
}
将slice设置为auto,将会允许elasticsearch选择slices的数量。这是设置一般是一个分配一个slice,直到指定的是设置。如果有多个source indices,elasticsearch将会根据分片的最小的数量选择slices的个数。
picking the number of slices
如何slices设置为auto,elasticsearch将会自动为大多数indices选择一个合理的数量。如果您手动设置slicing,请遵循以下准则:
当slices的数量等于索引的shards的数量时,查询性能最有效。如果这个数量太大(如500),请选择一个较小的数字,因为太多的切片会影响性能。设置高于shards数量的slices通常不会提高效率反而会增加开销。
update的性能与可用的slices数量呈正相关。
query和update的性能取决于文档的索引和集群的资源。
(7)pick up a new property
假设您创建了一个索引但是没有动态映射,然后向里面添加了数据,现在添加后一个mapping value可以从数据中获取更多的字段,如:
PUT test
{
"mappings":{
"_doc":{
"dynamic":false,
"properties":{
"text":{"type":"text"}
}
}
}
}
POST test/_doc?refresh
{
"text":"words words",
"flag":"bar"
}
POST test/_doc?refresh
{
"text":"words words",
"flag":"foo"
}
PUT test/_mapping/_doc
{
"properties":{
"text":{"type":"text"},
"flag":{"type":"text","analyzer":"keyword"}
}
}
注:"dynamic":false,表示这个新字段不会被索引,只是存储到了_source。为了获取这个新的字段您必须重新索引整个文档。
如:
POST test/_search?filter_path=hits.total
{
"query":{
"match":{
"flag":"foo"
}
}
}
不会查询到任何内容:
{
"hits":{
"total":0
}
}
但是您可以用_update_by_query请求获得新的mapping:
POST test/_update_by_query?refresh&conflicts=proceed
POST test/_search?filter_path=hits.total
{
"query":{
"match":{
"flag":"foo"
}
}
}
得到的响应为:
{
"hits":{
"total":1
}
}
添加多个字段时,也可以进行相同的操作。