用Query API删除 - shuiyuebingdian/ElasticSearch GitHub Wiki

Delete By Query API
最简单的用法是_delete_by_query在与查询匹配的每个文档上执行删除操作。这是API:

POST twitter/_delete_by_query
{
  "query": { 
	"match": {
	  "message": "some message"
	}
  }
}

查询必须以query为键,查询条件为值传递给请求,与Search API相同的方式作。您也可以使用q 与搜索API相同的方式使用参数。

这将返回如下内容:

{
  "took" : 147,
  "timed_out": false,
  "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,
  "total": 119,
  "failures" : [ ]
}

_delete_by_query在启动索引时获取索引的快照,并删除使用internal版本控制发现的索引。这意味着,如果在拍摄快照和处理删除请求之间更改文档,则会遇到版本冲突。当版本匹配时,将删除文档。

由于internal版本控制不支持将值0用作有效的版本号,因此无法使用删除版本等于零的文档,并且该文档 _delete_by_query将使请求失败。

在_delete_by_query执行期间,顺序执行多个搜索请求,以找到所有要删除的匹配文档。每次找到一批文档时,都会执行相应的批量请求以删除所有这些文档。如果搜索或批量请求被拒绝,则_delete_by_query 依靠默认策略重试被拒绝的请求(最多10次,并以指数方式退回)。达到最大重试次数限制将导致_delete_by_query 中止,并且所有失败都将在failures响应中返回。已经执行的删除仍然会保留。换句话说,该过程不会回滚,只会中止。当第一个失败导致中止时,失败的批量请求返回的所有失败都将在failures 元件; 因此,可能会有很多失败的实体。

如果您想计算版本冲突而不是使它们中止conflicts=proceed,请在url或"conflicts": "proceed"请求正文中进行设置。

回到API格式,您可以限制_delete_by_query为单一类型。这只会tweet从twitter索引中删除文档:

POST twitter/tweet/_delete_by_query?conflicts=proceed
{
  "query": {
	"match_all": {}
  }
}

也可以一次删除多个索引和多种类型的文档,就像搜索API一样:

POST twitter,blog/tweet,post/_delete_by_query
{
  "query": {
	"match_all": {}
  }
}

如果提供,routing则将路由复制到滚动查询,将过程限制为与该路由值匹配的分片:

POST twitter/_delete_by_query?routing=1
{
  "query": {
	"range" : {
		"age" : {
		   "gte" : 10
		}
	}
  }
}

默认情况下,_delete_by_query使用滚动批处理1000。您可以在URL中使用scroll_size参数更改批处理大小: POST twitter/_delete_by_query?scroll_size=5000 { "query": { "term": { "user": "kimchy" } } }

URL参数

除了标准的参数,如pretty,通过查询API删除也支持refresh,wait_for_completion,wait_for_active_shards,和timeout。

refresh请求完成后,发送将会刷新查询所涉及的所有分片。这与Delete API的refresh 参数不同,后者仅导致接收到删除请求的分片被刷新。

如果请求包含,wait_for_completion=false则Elasticsearch将执行一些预检检查,启动请求,然后返回task ,可与Tasks API 一起使用来取消或获取任务的状态。Elasticsearch还将在创建此任务的记录上作为文档.tasks/task/${taskId}。您可以根据自己的喜好保留或删除此文件。完成后,将其删除,以便Elasticsearch可以回收其使用的空间。

wait_for_active_shards控制在进行请求之前必须处于活动状态的分片副本数。有关 详细信息,请参见此处。timeout控制每个写入请求等待不可用的碎片变为可用的时间。两者都在Bulk API中完全一样地工作 。

requests_per_second可以被设置为任何正十进制数(1.4,6, 1000等)和节气门速率_delete_by_query通过填充每批用的等待时间问题的删除操作的批次。将设置requests_per_second为可以禁用节流-1。

节流是通过在批处理之间等待来完成的,以便_delete_by_query可以给内部使用的滚动 指定一个超时,该超时要考虑填充。填充时间是批大小除以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创建许多请求,然后等待一段时间,然后再开始下一组请求。这是“突发的”而不是“平滑的”。默认值为-1。

反应体 JSON响应如下所示:

{
  "took" : 639,
  "deleted": 0,
  "batches": 1,
  "version_conflicts": 2,
  "retries": 0,
  "throttled_millis": 0,
  "failures" : [ ]
}

took
从整个操作开始到结束的毫秒数。
deleted
成功删除的文档数。
batches
由delete by查询拉回的滚动响应数。
version_conflicts
被查询删除导致的版本冲突数量。
retries
通过查询删除以响应已满队列的重试次数。
throttled_millis
要求遵守的毫秒数requests_per_second。
failures
所有索引失败的数组。如果这是非空的,则请求由于这些失败而中止。有关conflicts如何防止版本冲突中止操作的信息,请参阅。 与Task API配合使用 您可以使用Task API获取所有正在运行的按查询删除请求的状态 :

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加上重要的total字段一样。total是重新索引期望执行的操作总数。您可以通过添加估计的进展updated,created以及deleted多个领域。当它们的总和等于total字段时,请求将结束。

,您可以使用任务ID直接查找任务:

GET /_tasks/taskId:1

该API的优势在于它与之集成wait_for_completion=false 以透明地返回已完成任务的状态。如果任务已完成并wait_for_completion=false设置在任务上,则它将返回 results或error字段。此功能的成本是在wait_for_completion=false创建的文档 .tasks/task/${taskId}。删除该文档由您决定。

与Cancel Task API一起使用 可以使用Task Cancel API取消所有“按查询删除”功能:

POST _tasks/task_id1/_cancel 

在task_id可以使用上述任务的API被发现。

取消应该很快发生,但可能需要几秒钟。上面的任务状态API将继续列出任务,直到被唤醒以取消自身为止。

重新调节

requests_per_second可以使用_rethrottleAPI 通过查询在运行的删除中更改的值:

POST _delete_by_query/task_id:1/_rethrottle?requests_per_second=-1

在task_id可以使用上述任务的API被发现。

就像在_delete_by_queryAPI requests_per_second 上进行设置一样,可以-1禁用限制或任何十进制数字,1.7或12将其限制为该级别。重新调整以加快查询的速度会立即生效,但重新调整以使查询的速度缓慢将在完成当前批处理后生效。这样可以防止滚动超时。

手动切片

按查询删除支持切片滚动,使您可以相对轻松地手动并行化过程:

POST twitter/_delete_by_query
{
  "slice": {
	"id": 0,
	"max": 2
  },
  "query": {
	"range": {
	  "likes": {
		"lt": 10
	  }
	}
  }
}
POST twitter/_delete_by_query
{
  "slice": {
	"id": 1,
	"max": 2
  },
  "query": {
	"range": {
	  "likes": {
		"lt": 10
	  }
	}
  }
}

您可以用下面的命令验证:

GET _refresh
POST twitter/_search?size=0&filter_path=hits.total
{
  "query": {
	"range": {
	  "likes": {
		"lt": 10
	  }
	}
  }
}

结果total是这样的:

{
  "hits": {
	"total": 0
  }
}

自动切片

您还可以使用“ 切片滚动”让“按查询删除”自动并行化 以切片_uid:

POST twitter/_delete_by_query?refresh&slices=5
{
  "query": {
	"range": {
	  "likes": {
		"lt": 10
	  }
	}
  }
}

验证:

POST twitter/_search?size=0&filter_path=hits.total
{
  "query": {
	"range": {
	  "likes": {
		"lt": 10
	  }
	}
  }
}

结果total是这样的:

{
  "hits": {
	"total": 0
  }
} 

添加slices到_delete_by_query可以自动完成上一节中使用的手动过程,创建子请求,这意味着它有一些怪癖:

  • 您可以在Tasks API中看到这些请求 。这些子请求是带有的请求任务的“子”任务slices。
  • 获取请求的任务状态slices仅包含已完成切片的状态。
  • 这些子请求可分别用于取消和限制操作。
  • 重新限制请求slices将按比例重新限制未完成的子请求。
  • 用取消请求slices将取消每个子请求。
  • 由于slices每个子请求的性质,将无法获得完全均匀的文档部分。将处理所有文档,但是某些切片可能比其他切片大。期望更大的切片具有更均匀的分布。
  • 带有requests_per_second和size带有请求的 参数与slices 每个子请求成比例地分布。结合以上关于分布不均的观点,您应该得出结论,使用 sizewith slices可能不会完全对size文档_delete_by_query进行编辑。
  • 每个子请求都将获得源索引的快照略有不同的快照,尽管它们都是在大约同一时间拍摄的。

挑选切片数

此时,我们slices对使用的数量提出了一些建议(max如果手动并行化,则使用slice API中的参数):

  • 不要使用大量数字。500会造成相当大的CPU抖动。
  • 从查询性能的角度来看,在源索引中使用分片数量的一些倍数会更有效。
  • 从查询性能的角度来看,使用与源索引中的数量一样多的分片是最有效的。
  • 索引性能应在可用资源范围内线性扩展,数量为slices。
  • 索引还是查询性能在该过程中占主导地位,取决于许多因素,例如要重新建立索引的文档以及正在执行重新建立索引的集群。