通过查询更新

The Update By Query 对象

The Update By Query 对象允许使用 _update_by_query 端点对匹配搜索查询的文档执行更新。

该对象实现为 Search 对象的修改,包含其查询方法的子集,以及一个脚本方法,用于进行更新。

The Update By Query 对象实现了以下 Search 查询类型

  • 查询

  • 过滤器

  • 排除

有关查询的更多信息,请参阅 Search DSL 章节。

Search 对象一样,API 设计为可链接的。这意味着 Update By Query 对象是不可变的:对该对象的所有更改都将导致创建包含更改的浅拷贝。这意味着您可以安全地将 Update By Query 对象传递给外部代码,而不必担心它会修改您的对象,只要它坚持使用 Update By Query 对象 API。

您可以通过多种方式定义您的客户端,但首选方法是使用全局配置。有关定义客户端的更多信息,请参阅 Configuration 章节。

定义完客户端后,您可以如下所示实例化 Update By Query 对象的副本

from elasticsearch_dsl import UpdateByQuery

ubq = UpdateByQuery().using(client)
# or
ubq = UpdateByQuery(using=client)

注意

所有方法都返回对象的副本,使其可以安全地传递给外部代码。

API 是可链接的,允许您在一个语句中组合多个方法调用

ubq = UpdateByQuery().using(client).query("match", title="python")

要将请求发送到 Elasticsearch

response = ubq.execute()

需要注意的是,使用脚本方法进行链接存在限制:多次调用脚本将覆盖先前值。也就是说,一次调用只能发送一个脚本。尝试使用两个脚本将导致仅存储第二个脚本。

鉴于以下示例

ubq = UpdateByQuery().using(client).script(source="ctx._source.likes++").script(source="ctx._source.likes+=2")

这意味着此客户端存储的脚本将是 'source': 'ctx._source.likes+=2',而之前的调用将不会被存储。

为了调试目的,您可以将 Update By Query 对象显式序列化为 dict

print(ubq.to_dict())

此外,要在脚本中使用变量,请参见以下示例

ubq.script(
  source="ctx._source.messages.removeIf(x -> x.somefield == params.some_var)",
  params={
    'some_var': 'some_string_val'
  }
)

序列化和反序列化

搜索对象可以使用 .to_dict() 方法序列化为字典。

您还可以使用 from_dict 类方法从 dict 创建 Update By Query 对象。这将创建一个新的 Update By Query 对象,并使用字典中的数据对其进行填充

ubq = UpdateByQuery.from_dict({"query": {"match": {"title": "python"}}})

如果您希望修改现有的 Update By Query 对象,覆盖其属性,请改用 update_from_dict 方法,该方法会就地更改实例

ubq = UpdateByQuery(index='i')
ubq.update_from_dict({"query": {"match": {"title": "python"}}, "size": 42})

额外属性和参数

要设置搜索请求的额外属性,请使用 .extra() 方法。这可用于定义无法通过特定 API 方法(如 explain)定义的主体中的键

ubq = ubq.extra(explain=True)

要设置查询参数,请使用 .params() 方法

ubq = ubq.params(routing="42")

响应

您可以通过调用 .execute() 方法来执行搜索,该方法将返回一个 Response 对象。The Response 对象允许您通过属性访问访问响应字典中的任何键。它还提供了一些方便的帮助程序

response = ubq.execute()

print(response.success())
# True

print(response.took)
# 12

如果您想检查 response 对象的内容,只需使用其 to_dict 方法即可获取原始数据以进行漂亮打印。