Elasticsearch(es)删除文档的多种方法(附带实例)
想要删除文档,有两种方法,分别是通过 ID 删除或通过查询删除。使用前一种方法可以删除单个文档,使用后一种方法则可以一次性删除多个文档。
通过查询删除时,可以设置过滤条件。例如,删除 status 字段为 unpublished 的文档或上个月的文档)。
接下来,我们来看一下这两种方法的实际操作。
根据要删除的文档的 ID,我们通过指定索引、_doc 端点和文档 ID 来构造 URL。例如,我们可以调用下面示例代码中的查询从 movies 索引中删除 ID 为 1 的文档。
如果文档未被删除(例如,它不在我们的存储中),我们会收到一个 result 值设为 not_found 的响应(状态码为 404)。有趣的是,如果删除操作成功,Elasticsearch 会递增 _version 标志的值。
例如,如果想删除所有由 James Cameron 执导的电影,可以编写下面示例代码所示的查询:
这个 POST 的请求体使用了一种特殊的语法,称为 Query DSL(领域特定语言),它允许我们传入各种属性,如 term、range 和 match,类似于基本的搜索查询。
注意,_delete_by_query 是一个功能强大的端点,能够处理复杂的删除条件。下面再看几个例子。
有时我们可能希望删除某个范围内(如评分在 3.5 到 4.5 之间的电影、在两个日期之间取消的航班等)的记录。我们可以使用 range 查询为这类需求的值的范围设置条件。
下面的示例代码中使用 _delete_by_query 删除票房在 3.5 亿美元到 4 亿美元之间的电影:
我们还可以构造复杂的查询。例如,下面的示例代码展示了一个查询,目的是删除由 Steven Spielberg 执导的、评分在 9 到 9.5 之间且票房收入少于 1 亿美元的电影,代码中使用 bool 查询作为请求:
到目前为止,我们一直是在单个索引上删除文档。我们还可以通过在 API URL 中提供以逗号分隔的索引列表来删除多个索引中的文档。示例格式如下:
通过查询删除时,可以设置过滤条件。例如,删除 status 字段为 unpublished 的文档或上个月的文档)。
接下来,我们来看一下这两种方法的实际操作。
通过ID删除文档
我们可以通过在索引文档 API 上调用 HTTP DELETE 方法从 Elasticsearch 中删除单个文档:DELETE <index_name>/_doc/<id>此处的 URL 与我们用于索引和检索文档的 URL 相同。
根据要删除的文档的 ID,我们通过指定索引、_doc 端点和文档 ID 来构造 URL。例如,我们可以调用下面示例代码中的查询从 movies 索引中删除 ID 为 1 的文档。
DELETE movies/_doc/1从服务器收到的响应表明文档已成功删除:
{ ... "_id" : "1", "_version" : 2, "result" : "deleted" }响应返回一个 result 属性,值设为 deleted,通知客户端对象已成功删除。
如果文档未被删除(例如,它不在我们的存储中),我们会收到一个 result 值设为 not_found 的响应(状态码为 404)。有趣的是,如果删除操作成功,Elasticsearch 会递增 _version 标志的值。
通过查询删除文档
正如我们刚才看到的,删除单个文档很简单。如果我们想根据某个条件删除多个文档,可以使用 _delete_by_query。例如,如果想删除所有由 James Cameron 执导的电影,可以编写下面示例代码所示的查询:
POST movies/_delete_by_query { "query":{ "match":{ "director":"James Cameron" } } }在这里,我们使用 James Cameron 执导的所有电影作为搜索条件,在请求体中创建查询。匹配条件的文档将被标记并删除。
这个 POST 的请求体使用了一种特殊的语法,称为 Query DSL(领域特定语言),它允许我们传入各种属性,如 term、range 和 match,类似于基本的搜索查询。
注意,_delete_by_query 是一个功能强大的端点,能够处理复杂的删除条件。下面再看几个例子。
有时我们可能希望删除某个范围内(如评分在 3.5 到 4.5 之间的电影、在两个日期之间取消的航班等)的记录。我们可以使用 range 查询为这类需求的值的范围设置条件。
下面的示例代码中使用 _delete_by_query 删除票房在 3.5 亿美元到 4 亿美元之间的电影:
POST movies/_delete_by_query { "query": { "range": { "gross_earnings_in_millions": { "gt": 350, "lt": 400 } } } }这里,_delete_by_query 接受一个带有匹配条件的 range 查询:查找票房在 3.5 亿美元到 4 亿美元之间的文档。正如我们所期望的那样,所有匹配的文档都被删除了。
我们还可以构造复杂的查询。例如,下面的示例代码展示了一个查询,目的是删除由 Steven Spielberg 执导的、评分在 9 到 9.5 之间且票房收入少于 1 亿美元的电影,代码中使用 bool 查询作为请求:
POST movies/_delete_by_query { "query": { "bool": { "must": [{ ←--- 匹配由Spielberg执导的电影 "match": { "director": "Steven Spielberg" } } ], "must_not": [{ ←--- 评分应大于9但小于9.5 "range": { "imdb_rating": { "gte": 9, "lte": 9.5 } } } ], "filter": [{ ←--- 票房不应低于1亿美元 "range": { "gross_earnings_in_millions": { "lt": 100 } } } ] } } }该查询使用了一种称为 bool 查询的复杂查询逻辑,它组合了多个较小的查询以实现复杂的搜索需求。
删除所有文档
可以使用 match_all 查询从索引中删除整个文档集,示例代码如下:注意,删除操作是不可逆的!在向 Elasticsearch 发送删除查询时务必谨慎。
POST movies/_delete_by_query { "query": { "match_all": {} } }这段代码执行了一个 match_all 查询。它匹配所有文档并同时删除它们。这是一个破坏性操作,因此在删除整个文档集时要小心!我们还可以通过发出 DELETE movies 命令来删除整个索引,但记住,这些都是不可逆的命令。
到目前为止,我们一直是在单个索引上删除文档。我们还可以通过在 API URL 中提供以逗号分隔的索引列表来删除多个索引中的文档。示例格式如下:
POST <index_1>,<index_2>,<index_3>/_delete_by_query下面的示例代码展示了如何删除多个与电影相关的索引中的所有文档。注意,我们可以使用 GET _cat/indices 列出所有索引:
POST old_movies,classics,movie_reviews/_delete_by_query { "query": { "match_all": {} } }再次提醒,执行 delete 查询时要格外小心,因为可能会丢失整个数据集!除非希望清除整个数据集,否则在生产环境中执行删除操作时务必谨慎。