根据查询删除 API
编辑根据查询删除 API编辑
删除与指定查询匹配的文档。
resp = client.delete_by_query( index="my-index-000001", body={"query": {"match": {"user.id": "elkbee"}}}, ) print(resp)
response = client.delete_by_query( index: 'my-index-000001', body: { query: { match: { 'user.id' => 'elkbee' } } } ) puts response
POST /my-index-000001/_delete_by_query { "query": { "match": { "user.id": "elkbee" } } }
请求编辑
POST /<target>/_delete_by_query
描述编辑
您可以在请求 URI 或请求正文中使用与 搜索 API 相同的语法来指定查询条件。
提交根据查询删除请求时,Elasticsearch 会在开始处理请求时获取数据流或索引的快照,并使用 内部
版本控制删除匹配的文档。如果文档在快照拍摄时间和删除操作处理时间之间发生更改,则会导致版本冲突,删除操作将失败。
版本号为 0 的文档无法使用根据查询删除进行删除,因为 内部
版本控制不支持 0 作为有效版本号。
在处理根据查询删除请求时,Elasticsearch 会顺序执行多个搜索请求以查找要删除的所有匹配文档。对每批匹配文档执行批量删除请求。如果搜索或批量请求被拒绝,则会最多重试 10 次,并以指数级退避。如果达到最大重试次数限制,则处理将停止,所有失败的请求都将返回到响应中。任何已成功完成的删除请求仍然有效,不会回滚。
您可以选择通过将 conflicts
设置为 proceed
来计算版本冲突,而不是停止并返回。请注意,如果您选择计算版本冲突,则操作可能会尝试从源中删除比 max_docs
更多的文档,直到它成功删除了 max_docs
个文档,或者它已遍历源查询中的所有文档。
刷新分片编辑
指定 refresh
参数会在请求完成后刷新参与根据查询删除的所有分片。这与删除 API 的 refresh
参数不同,后者会导致仅接收删除请求的分片被刷新。与删除 API 不同,它不支持 wait_for
。
异步运行根据查询删除编辑
如果请求包含 wait_for_completion=false
,则 Elasticsearch 会执行一些预检,启动请求,并返回一个 任务
,您可以使用它来取消或获取任务的状态。Elasticsearch 会在 .tasks/task/${taskId}
处将此任务的记录创建为文档。完成任务后,您应该删除任务文档,以便 Elasticsearch 可以回收空间。
等待活动分片编辑
wait_for_active_shards
控制在继续处理请求之前必须有多少个分片副本处于活动状态。有关详细信息,请参阅 活动分片。 timeout
控制每个写入请求等待不可用分片变为可用状态的时间。两者都与它们在 批量 API 中的工作方式完全相同。根据查询删除使用滚动搜索,因此您还可以指定 scroll
参数来控制它保持搜索上下文处于活动状态的时间,例如 ?scroll=10m
。默认值为 5 分钟。
限制删除请求编辑
要控制根据查询删除发出删除操作批次的速率,您可以将 requests_per_second
设置为任何正小数。这会在每个批次中添加等待时间以限制速率。将 requests_per_second
设置为 -1
以禁用限制。
限制使用批次之间的等待时间,以便内部滚动请求可以被赋予一个考虑请求填充时间的超时时间。填充时间是批次大小除以 requests_per_second
与写入花费的时间之间的差值。默认情况下,批次大小为 1000
,因此如果 requests_per_second
设置为 500
target_time = 1000 / 500 per second = 2 seconds wait_time = target_time - write_time = 2 seconds - .5 seconds = 1.5 seconds
由于批次作为单个 _bulk
请求发出,因此较大的批次大小会导致 Elasticsearch 创建许多请求并在开始下一组之前等待。这是“突发”而不是“平滑”。
切片编辑
根据查询删除支持 切片滚动 以并行化删除过程。这可以提高效率,并提供一种将请求分解为更小部分的便捷方法。
将 slices
设置为 auto
会为大多数数据流和索引选择一个合理的值。如果您正在手动切片或以其他方式调整自动切片,请记住
- 当
slices
的数量等于索引或后备索引中的分片数量时,查询性能最有效。如果该数字很大(例如,500),请选择一个较小的数字,因为过多的slices
会影响性能。将slices
设置为高于分片数量的值通常不会提高效率,还会增加开销。 - 删除性能随着切片数量的增加而线性扩展到可用资源。
查询性能或删除性能在运行时占主导地位取决于正在重新索引的文档和集群资源。
路径参数编辑
-
<target>
- (可选,字符串) 要搜索的数据流、索引和别名的逗号分隔列表。支持通配符 (
*
)。要搜索所有数据流或索引,请省略此参数或使用* 或 `_all
。
查询参数编辑
-
allow_no_indices
-
(可选,布尔值) 如果为
false
,则如果任何通配符表达式、索引别名 或_all
值仅针对缺少的或关闭的索引,则请求将返回错误。即使请求针对其他打开的索引,此行为也适用。例如,如果索引以foo
开头,但没有索引以bar
开头,则针对foo*,bar*
的请求将返回错误。默认为
true
。 -
analyzer
-
(可选,字符串) 用于查询字符串的分析器。
此参数只能在指定
q
查询字符串参数时使用。 -
analyze_wildcard
-
(可选,布尔值) 如果为
true
,则分析通配符和前缀查询。默认为false
。此参数只能在指定
q
查询字符串参数时使用。 -
conflicts
- (可选,字符串) 如果根据查询删除遇到版本冲突,该怎么办:
abort
或proceed
。默认为abort
。 -
default_operator
-
(可选,字符串) 查询字符串查询的默认运算符:AND 或 OR。默认为
OR
。此参数只能在指定
q
查询字符串参数时使用。 -
df
-
(可选,字符串) 用作默认值的字段,其中查询字符串中没有给出字段前缀。
此参数只能在指定
q
查询字符串参数时使用。 -
expand_wildcards
-
(可选,字符串) 通配符模式可以匹配的索引类型。如果请求可以针对数据流,则此参数确定通配符表达式是否匹配隐藏的数据流。支持逗号分隔的值,例如
open,hidden
。有效值为-
all
- 匹配任何数据流或索引,包括 隐藏 的数据流或索引。
-
open
- 匹配打开的、非隐藏的索引。还匹配任何非隐藏的数据流。
-
closed
- 匹配关闭的、非隐藏的索引。还匹配任何非隐藏的数据流。数据流无法关闭。
-
hidden
- 匹配隐藏的数据流和隐藏的索引。必须与
open
、closed
或两者结合使用。 -
none
- 不接受通配符模式。
默认为
open
。 -
-
ignore_unavailable
- (可选,布尔值) 如果为
false
,则如果请求针对缺少的或关闭的索引,则请求将返回错误。默认为false
。 -
lenient
-
(可选,布尔值) 如果为
true
,则会忽略查询字符串中基于格式的查询失败(例如,向数字字段提供文本)。默认为false
。此参数只能在指定
q
查询字符串参数时使用。 -
max_docs
- (可选,整数) 要处理的文档的最大数量。默认为所有文档。当设置为小于或等于
scroll_size
的值时,将不会使用滚动来检索操作的结果。 -
preference
- (可选,字符串) 指定应执行操作的节点或分片。默认情况下为随机。
-
q
- (可选,字符串) Lucene 查询字符串语法中的查询。
-
request_cache
- (可选,布尔值) 如果为
true
,则此请求使用请求缓存。默认为索引级别设置。 -
refresh
- (可选,布尔值) 如果为
true
,则 Elasticsearch 会在请求完成后刷新参与根据查询删除的所有分片。默认为false
。 -
requests_per_second
- (可选,整数) 此请求的节流,以每秒子请求数表示。默认为
-1
(无节流)。 -
routing
- (可选,字符串) 用于将操作路由到特定分片的自定义值。
-
scroll
- (可选,时间值) 用于保留搜索上下文以进行滚动的周期。请参阅滚动搜索结果。
-
scroll_size
- (可选,整数) 为操作提供支持的滚动请求的大小。默认为 1000。
-
search_type
-
(可选,字符串) 搜索操作的类型。可用选项
-
query_then_fetch
-
dfs_query_then_fetch
-
-
search_timeout
- (可选,时间单位) 每个搜索请求的显式超时时间。默认为无超时。
-
slices
- (可选,整数) 此任务应划分的切片数量。默认为 1,表示任务不会被切分成子任务。
-
sort
- (可选,字符串) 一个由 <field>:<direction> 对组成的逗号分隔列表。
-
stats
- (可选,字符串) 用于日志记录和统计目的的请求的特定
tag
。 -
terminate_after
-
(可选,整数) 每个分片要收集的文档的最大数量。如果查询达到此限制,Elasticsearch 将提前终止查询。Elasticsearch 在排序之前收集文档。
谨慎使用。Elasticsearch 将此参数应用于处理请求的每个分片。如果可能,让 Elasticsearch 自动执行提前终止。避免为针对跨多个数据层级具有后备索引的数据流的请求指定此参数。
-
timeout
- (可选,时间单位) 每个删除请求等待活动分片的周期。默认为
1m
(一分钟)。 -
version
- (可选,布尔值) 如果为
true
,则将文档版本作为命中的一部分返回。 -
wait_for_active_shards
-
(可选,字符串) 在继续操作之前必须处于活动状态的分片副本数量。设置为
all
或任何正整数,直到索引中的分片总数 (number_of_replicas+1
)。默认值:1,主分片。请参阅活动分片。
响应正文编辑
JSON 响应如下所示
{ "took" : 147, "timed_out": false, "total": 119, "deleted": 119, "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
- 成功处理的文档数量。
-
deleted
- 成功删除的文档数量。
-
batches
- 按查询删除拉取的滚动响应数量。
-
version_conflicts
- 按查询删除遇到的版本冲突数量。
-
noops
- 此字段对于按查询删除始终等于零。它只存在,以便按查询删除、按查询更新和重新索引 API 返回具有相同结构的响应。
-
retries
- 按查询删除尝试的重试次数。
bulk
是重试的批量操作数量,而search
是重试的搜索操作数量。 -
throttled_millis
- 请求为了符合
requests_per_second
而休眠的毫秒数。 -
requests_per_second
- 按查询删除期间实际执行的每秒请求数。
-
throttled_until_millis
- 此字段在
_delete_by_query
响应中始终应等于零。它只有在使用任务 API时才有意义,在该 API 中,它指示为了符合requests_per_second
,下次(以自纪元以来的毫秒数表示)将再次执行节流请求的时间。 -
failures
- 如果在过程中出现任何不可恢复的错误,则为错误数组。如果此数组不为空,则请求由于这些错误而中止。按查询删除是使用批次实现的,任何错误都会导致整个过程中止,但当前批次中的所有错误都会收集到数组中。您可以使用
conflicts
选项来防止重新索引在版本冲突时中止。
示例编辑
从 my-index-000001
数据流或索引中删除所有文档
resp = client.delete_by_query( index="my-index-000001", conflicts="proceed", body={"query": {"match_all": {}}}, ) print(resp)
response = client.delete_by_query( index: 'my-index-000001', conflicts: 'proceed', body: { query: { match_all: {} } } ) puts response
POST my-index-000001/_delete_by_query?conflicts=proceed { "query": { "match_all": {} } }
从多个数据流或索引中删除文档
resp = client.delete_by_query( index=["my-index-000001", "my-index-000002"], body={"query": {"match_all": {}}}, ) print(resp)
response = client.delete_by_query( index: 'my-index-000001,my-index-000002', body: { query: { match_all: {} } } ) puts response
POST /my-index-000001,my-index-000002/_delete_by_query { "query": { "match_all": {} } }
将按查询删除操作限制为具有特定路由值的 shard
resp = client.delete_by_query( index="my-index-000001", routing="1", body={"query": {"range": {"age": {"gte": 10}}}}, ) print(resp)
response = client.delete_by_query( index: 'my-index-000001', routing: 1, body: { query: { range: { age: { gte: 10 } } } } ) puts response
POST my-index-000001/_delete_by_query?routing=1 { "query": { "range" : { "age" : { "gte" : 10 } } } }
默认情况下,_delete_by_query
使用 1000 的滚动批次。您可以使用 scroll_size
URL 参数更改批次大小
resp = client.delete_by_query( index="my-index-000001", scroll_size="5000", body={"query": {"term": {"user.id": "kimchy"}}}, ) print(resp)
response = client.delete_by_query( index: 'my-index-000001', scroll_size: 5000, body: { query: { term: { 'user.id' => 'kimchy' } } } ) puts response
POST my-index-000001/_delete_by_query?scroll_size=5000 { "query": { "term": { "user.id": "kimchy" } } }
使用唯一属性删除文档
resp = client.delete_by_query( index="my-index-000001", body={"query": {"term": {"user.id": "kimchy"}}, "max_docs": 1}, ) print(resp)
response = client.delete_by_query( index: 'my-index-000001', body: { query: { term: { 'user.id' => 'kimchy' } }, max_docs: 1 } ) puts response
POST my-index-000001/_delete_by_query { "query": { "term": { "user.id": "kimchy" } }, "max_docs": 1 }
手动切片编辑
通过提供切片 ID 和切片总数,手动切片按查询删除
resp = client.delete_by_query( index="my-index-000001", body={ "slice": {"id": 0, "max": 2}, "query": {"range": {"http.response.bytes": {"lt": 2000000}}}, }, ) print(resp) resp = client.delete_by_query( index="my-index-000001", body={ "slice": {"id": 1, "max": 2}, "query": {"range": {"http.response.bytes": {"lt": 2000000}}}, }, ) print(resp)
response = client.delete_by_query( index: 'my-index-000001', body: { slice: { id: 0, max: 2 }, query: { range: { 'http.response.bytes' => { lt: 2_000_000 } } } } ) puts response response = client.delete_by_query( index: 'my-index-000001', body: { slice: { id: 1, max: 2 }, query: { range: { 'http.response.bytes' => { lt: 2_000_000 } } } } ) puts response
POST my-index-000001/_delete_by_query { "slice": { "id": 0, "max": 2 }, "query": { "range": { "http.response.bytes": { "lt": 2000000 } } } } POST my-index-000001/_delete_by_query { "slice": { "id": 1, "max": 2 }, "query": { "range": { "http.response.bytes": { "lt": 2000000 } } } }
您可以验证它是否有效
resp = client.indices.refresh() print(resp) resp = client.search( index="my-index-000001", size="0", filter_path="hits.total", body={"query": {"range": {"http.response.bytes": {"lt": 2000000}}}}, ) print(resp)
response = client.indices.refresh puts response response = client.search( index: 'my-index-000001', size: 0, filter_path: 'hits.total', body: { query: { range: { 'http.response.bytes' => { lt: 2_000_000 } } } } ) puts response
GET _refresh POST my-index-000001/_search?size=0&filter_path=hits.total { "query": { "range": { "http.response.bytes": { "lt": 2000000 } } } }
这将导致一个合理的 total
,例如
{ "hits": { "total" : { "value": 0, "relation": "eq" } } }
使用自动切片编辑
您也可以让按查询删除使用切片滚动在 _id
上自动并行化。使用 slices
指定要使用的切片数量
resp = client.delete_by_query( index="my-index-000001", refresh=True, slices="5", body={"query": {"range": {"http.response.bytes": {"lt": 2000000}}}}, ) print(resp)
response = client.delete_by_query( index: 'my-index-000001', refresh: true, slices: 5, body: { query: { range: { 'http.response.bytes' => { lt: 2_000_000 } } } } ) puts response
POST my-index-000001/_delete_by_query?refresh&slices=5 { "query": { "range": { "http.response.bytes": { "lt": 2000000 } } } }
您也可以验证它是否有效
resp = client.search( index="my-index-000001", size="0", filter_path="hits.total", body={"query": {"range": {"http.response.bytes": {"lt": 2000000}}}}, ) print(resp)
response = client.search( index: 'my-index-000001', size: 0, filter_path: 'hits.total', body: { query: { range: { 'http.response.bytes' => { lt: 2_000_000 } } } } ) puts response
POST my-index-000001/_search?size=0&filter_path=hits.total { "query": { "range": { "http.response.bytes": { "lt": 2000000 } } } }
这将导致一个合理的 total
,例如
{ "hits": { "total" : { "value": 0, "relation": "eq" } } }
将 slices
设置为 auto
将让 Elasticsearch 选择要使用的切片数量。此设置将使用每个 shard 一个切片,直到达到某个限制。如果有多个源数据流或索引,它将根据 shard 数量最少的索引或后备索引选择切片数量。
将 slices
添加到 _delete_by_query
只是自动执行了上面部分中使用的手动过程,创建子请求,这意味着它有一些怪癖
- 您可以在任务 API中看到这些请求。这些子请求是具有
slices
的请求的任务的“子”任务。 - 获取具有
slices
的请求的任务状态只包含已完成切片的状态。 - 这些子请求对于取消和重新节流等操作是可单独寻址的。
- 重新节流具有
slices
的请求将按比例重新节流未完成的子请求。 - 取消具有
slices
的请求将取消每个子请求。 - 由于
slices
的性质,每个子请求都不会获得文档的完全均匀部分。所有文档都将被处理,但一些切片可能比其他切片更大。预计较大的切片将具有更均匀的分布。 - 像
requests_per_second
和max_docs
这样的参数在具有slices
的请求中会按比例分配给每个子请求。将这一点与上面关于分布不均匀的观点结合起来,您应该得出结论,使用max_docs
和slices
可能不会导致正好删除max_docs
个文档。 - 每个子请求都会获得源数据流或索引的略微不同的快照,尽管这些快照都是在近似相同的时间拍摄的。
更改请求的节流编辑
可以使用 _rethrottle
API 更改正在运行的按查询删除的 requests_per_second
的值。立即生效的重新节流会加快查询速度,但重新节流会减慢查询速度,直到完成当前批次以防止滚动超时。
$params = [ 'task_id' => 'r1A2WoRbTwKZ516z6NEs5A:36619', ]; $response = $client->deleteByQueryRethrottle($params);
resp = client.delete_by_query_rethrottle( task_id="r1A2WoRbTwKZ516z6NEs5A:36619", requests_per_second="-1", ) print(resp)
response = client.delete_by_query_rethrottle( task_id: 'r1A2WoRbTwKZ516z6NEs5A:36619', requests_per_second: -1 ) puts response
res, err := es.DeleteByQueryRethrottle( "r1A2WoRbTwKZ516z6NEs5A:36619", esapi.IntPtr(-1), ) fmt.Println(res, err)
const response = await client.deleteByQueryRethrottle({ task_id: 'r1A2WoRbTwKZ516z6NEs5A:36619', requests_per_second: '-1' }) console.log(response)
POST _delete_by_query/r1A2WoRbTwKZ516z6NEs5A:36619/_rethrottle?requests_per_second=-1
使用任务 API获取任务 ID。将 requests_per_second
设置为任何正小数或 -1
以禁用节流。
获取按查询删除操作的状态编辑
使用任务 API获取按查询删除操作的状态
$response = $client->tasks()->list();
resp = client.tasks.list( detailed="true", actions="*/delete/byquery", ) print(resp)
response = client.tasks.list( detailed: true, actions: '*/delete/byquery' ) puts response
res, err := es.Tasks.List( es.Tasks.List.WithActions("*/delete/byquery"), es.Tasks.List.WithDetailed(true), ) fmt.Println(res, err)
const response = await client.tasks.list({ detailed: 'true', actions: '*/delete/byquery' }) console.log(response)
GET _tasks?detailed=true&actions=*/delete/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/delete/byquery", "status" : { "total" : 6154, "updated" : 0, "created" : 0, "deleted" : 3500, "batches" : 36, "version_conflicts" : 0, "noops" : 0, "retries": 0, "throttled_millis": 0 }, "description" : "" } } } } }
此对象包含实际状态。它与响应 JSON 相同,重要的是增加了 |
使用任务 ID,您可以直接查找任务
$params = [ 'task_id' => 'r1A2WoRbTwKZ516z6NEs5A:36619', ]; $response = $client->tasks()->get($params);
resp = client.tasks.get( task_id="r1A2WoRbTwKZ516z6NEs5A:36619", ) print(resp)
response = client.tasks.get( task_id: 'r1A2WoRbTwKZ516z6NEs5A:36619' ) puts response
res, err := es.Tasks.Get( "r1A2WoRbTwKZ516z6NEs5A:36619", ) fmt.Println(res, err)
const response = await client.tasks.get({ task_id: 'r1A2WoRbTwKZ516z6NEs5A:36619' }) console.log(response)
GET /_tasks/r1A2WoRbTwKZ516z6NEs5A:36619
此 API 的优点是它与 wait_for_completion=false
集成,以透明地返回已完成任务的状态。如果任务已完成并且在该任务上设置了 wait_for_completion=false
,那么它将返回 results
或 error
字段。此功能的代价是在 .tasks/task/${taskId}
上创建的 wait_for_completion=false
文档。您需要删除该文档。
取消按查询删除操作编辑
可以使用任务取消 API取消任何按查询删除。
$params = [ 'task_id' => 'r1A2WoRbTwKZ516z6NEs5A:36619', ]; $response = $client->tasks()->cancel($params);
resp = client.tasks.cancel( task_id="r1A2WoRbTwKZ516z6NEs5A:36619", ) print(resp)
response = client.tasks.cancel( task_id: 'r1A2WoRbTwKZ516z6NEs5A:36619' ) puts response
res, err := es.Tasks.Cancel( es.Tasks.Cancel.WithTaskID("r1A2WoRbTwKZ516z6NEs5A:36619"), ) fmt.Println(res, err)
const response = await client.tasks.cancel({ task_id: 'r1A2WoRbTwKZ516z6NEs5A:36619' }) console.log(response)
POST _tasks/r1A2WoRbTwKZ516z6NEs5A:36619/_cancel
可以使用任务 API找到任务 ID。
取消应该很快发生,但可能需要几秒钟。上面的任务状态 API 将继续列出按查询删除任务,直到此任务检查它是否已取消并自行终止。