12、update_by_query API

原文地址: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来更改执行的操作:

  • noop:如果脚本决定不需要进行任何更改,则设置ctx.op=noop。这将导致_update_by_query从其更新中忽略该文档。此无操作将在响应体的noop计数器中报告。
  • delete:如果你想要删除该文档,设置ctx.op=delete。删除操作会在响应体的deleted计数器中报告。

将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

  • 除了常规的参数像pretty,_update_by_query接口也支持refresh、wait_for_comletion,wait_for_active_shards,timeout和scroll。
  • refresh:设置refresh参数将会更新所有的index的分片,这和updata API的refresh不同,update API的refresh仅更新收到新数据的index。_update_by_query也不支持wait_for.
  • wait_for_completion:设置wait_for_completion=false,elasticsearch将于执行一些预检查,发送请求,然后返回一个task,可以用来取消或是获取task的状态。elasticsearch将会在.tasks/task/${taskId}目录粗昂见一个文档。您可以根据需要保留或是删除该文档。当您用完之后删除该文档,elasticsearch可以回收使用的空间。
  • wait_for_active_shards:控制在执行请求前需要有几个分片的复本。
  • timeout:控制每个请求等待分片从不可用状态到可用状态的时间。
  • request_per_second:可以设置为任意十进制数,如1.4,6,1000等。当requests_per_second设置为-1是禁用该控制。

(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" : [ ]
}
  • took:整个操作花费的毫秒数。
  • timed_out:在执行期间任何查询或更新操作超时这个值就会是true。
  • total:总共涉及多少个documents
  • updated:成功的更新了多少个documents
  • deleted:成功的删除了多少个documents
  • batches:回滚响应数
  • verison_conflicts:执行过程中遇到的存在冲突的版本
  • noops:由于ctx.op=noop设置造成的忽略的documents数
  • retries:重复尝试的次数,bulk,bulk重复尝试的次数,search,查询重复尝试的次数
  • throthled_millis:requests_per_second参数引起的请求等待时间
  • requests_per_second:在执行期间每秒有效的执行次数
  • throttled_until_millis:此参数在_update_by_query时一直是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
    }
}

添加多个字段时,也可以进行相同的操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值