Elasticsearch:升级到 elasticsearch-py 8.x 的 10 个理由

2024-01-09 12:40:52

作者:来自 Elastic 公司?Quentin_Pradet

早在 2022 年 2 月,当 Elasticsearch 8.0 发布时,Python 客户端也发布了 8.0 版本。 它是 7.x 客户端的部分重写,并附带了许多不错的功能(概述如下),但也有弃用警告和重大更改。 如今,7.17 版客户端仍然相对受欢迎,每月下载量超过 100 万次,约占 8.x 下载量的 50%

作为 Elasticsearch Python 客户端的新维护者,我希望我们的社区能够从我们在客户端中所做的改进中受益,通过帮助所有 elasticsearch-py 用户:

  • 帮助 7.17 用户迁移到 8.x,
  • 帮助 8.x 用户利用新功能。

根据我作为 urllib3 维护者的经验,我知道投资 urllib3 2.0 迁移指南?并帮助用户迁移是有回报的。 同样,我们现在正在努力通过删除弃用警告和重大更改来使 elasticsearch-py 8.x 更易于使用。 这篇文章重点介绍了升级到 8.x 的充分理由:这些理由在近两年内都是如此,但最近的理由也是如此。 顺便说一句,如果你已经确信,请查看我们的迁移指南(如果你遇到困难,请务必联系我们!):

Migrating to 8.0 | Elasticsearch Python Client [8.11] | Elastic

话不多说,以下是使用 elasticsearch-py 8.x 的十个理由。

1. 支持最新的 Elasticsearch API

Elasticsearch 8 是 Elasticsearch 的最佳版本,全面进行了许多改进,并大大增加了可扩展性。更重要的是,对于我们对 Python 客户端的讨论,添加了各种新的 API:

由于客户端是根据 Elasticsearch 规范生成的,因此可以保证获得最新、最好的 API。

2. Elasticsearch DSL 客户端 8.x

Elasticsearch DSL 客户端 ?是一个高级库,其目的是帮助以更简洁的方式编写和运行针对 Elasticsearch 的查询。 使用与之前文章相同的 christmas_characters 索引作为示例:

response = client.search(
    index="christmas_characters",
    query={
        "bool": {
            "must": [{"match": {"behavior": "good"}}]
        }
    }
)

for hit in response['hits']['hits']:
    print(hit['_score'], hit['_source']['title'])

变成:

s = Search(using=client, index="christmas_characters").query("match", behavior="good")

for hit in s.execute():
    print(hit.meta.score, hit.title)

你要么喜欢它的简洁性,要么讨厌学习新的 DSL,但这个客户端非常受欢迎,每月下载量超过 300 万次,并拥有专门的用户群。 它过去维护得很差,一直停留在 7.4.1 版本,但我在 9 月份发布了 8.9.0 版本,这是第一个与主要 Python 客户端版本 8 兼容的版本。

我致力于维护它,并于上个月发布了 8.11.0,以支持 Python 3.12 并允许折叠(collapsing queries)查询(相关 GitHub 问题已累积 38 票!)。

3.?种类型提示和更多 Pythonic API

从 Elasticsearch Python 客户端的早期(早在 2013 年 7 月起!)开始,body 参数就是为接受它的请求指定请求正文的方法。 使用 body 的 API 调用如下所示:

es.search(
    index="christmas_characters",
    body={
        "query": {"match_all": {}},
        "size": 50,
    }
)

然而,这个参数是一个无类型的 Python 字典,没有经过客户端验证,这意味着在将请求发送到服务器之前你无法判断你的请求是否正确。 但你不想了解生产中的基本问题! 因此,elasticsearch-py 8.0 利用 Elasticsearch 规范引入了更好的 API,该规范提供了每个 API 的完整类型。 第一层主体键可以使用 Python 参数指定:

es.search(
    index="christmas_characters",
    query={"match_all": {}},
    size=50,
)

这具有多种优点,包括更好的自动完成和类型检查。 例如,如果 size 不是整数,mypy 将引发错误。 因为我们意识到我们可以将 body unpack?为类型化参数,如下所示:

es.search(
    index="christmas_characters",
    **{"query": {"match_all": {}}, "size": 50}
)

我们决定在 elasticsearch-py 8.0 中完全弃用 body 参数。

4. 恢复 body 参数

然而,弃用 body 有以下缺点:

  • 过去十年编写的许多代码现在都触发了弃用警告
  • 未知参数(例如 sub_searches 或 Elasticsearch 规范中的无意遗漏)被拒绝,导致查询彻底失败,不必要地强制使用原始请求。
  • 诸如传递已编码主体以避免支付序列化 JSON 成本之类的优化已不再可能。

客户端的原作者 Honza Král 指出了这些问题 ,我们决定让 body 与新 API 一起像以前一样工作,没有任何警告。 这将在 elasticsearch-py 8.12 中提供,我们希望这将有助于 elasticsearch-py 8.x 的采用。

5. 记录调试请求

elasticsearch-py 8.x 客户端基于 elastic-transport 库,可以作为不同客户端的基础。 该库引入了一个非常有用的功能来调试请求和响应,通过调用 elastic_transport.debug_logging() 来启用。

import elastic_transport
from elasticsearch import Elasticsearch

# In this example we're debugging an Elasticsearch client:
client = Elasticsearch(...)
# Use `elastic_transport.debug_logging()` before the request
elastic_transport.debug_logging()

client.search(
    index="christmas_characters",
    query={
        "bool": {
            "must": [{"match": {"behavior": "good"}}]
        }
    }
)

上述脚本将输出以下日志:

[2021-11-23T14:11:20] > POST /example-index/_search?typed_keys=true HTTP/1.1
> Accept: application/json
> Accept-Encoding: gzip
> Authorization: Basic <hidden>
> Connection: keep-alive
> Content-Encoding: gzip
> Content-Type: application/json
> User-Agent: elastic-transport-python/8.11.0+dev
> X-Elastic-Client-Meta: es=8.11.0p,py=3.12.0,t=8.11.0p,ur=2.1.0
> {"query":{"match":{"text-field":"value"}}}
< HTTP/1.1 200 OK
< Content-Encoding: gzip
< Content-Length: 165
< Content-Type: application/json;charset=utf-8
< Date: Tue, 12 Dec 2022 20:11:20 GMT
< X-Cloud-Request-Id: ctSE59hPSCugrCPM4A2GUQ
< X-Elastic-Product: Elasticsearch
< X-Found-Handling-Cluster: 40c9b5837c8f4dd083f05eac950fd50c
< X-Found-Handling-Instance: instance-0000000001
< {"hits":{...}}

从我了解到这个功能的那天起,这个功能就成为了我开发工作流程的重要组成部分,现在我在其他客户端中怀念它:它就是那么好!

6. 全链 SSL/TLS 指纹固定

当通过 HTTPS 与 Elasticsearch 通信时(这是从 Elasticsearch 8 开始的默认设置),客户端需要能够验证服务器正在使用的证书,就像你的浏览器在获取单词之前必须验证 discuss.elastic.co 的证书一样 您当前正在阅读。 这是通过跟踪证书链直至根证书颁发机构(根 CA)来实现的。 但是,该根 CA 不一定是已受信任的通用根 CA,而可能是整个公司使用的企业根 CA,甚至可能是 Elasticsearch 为单个集群生成的根 CA

在这些情况下,有两种方法可以正确验证证书:

  1. 将相关的证书颁发机构存储在文件中,并配置 ca_certs 参数。 然而,存储此文件需要额外的步骤,并且访问公共证书并不总是那么容易。
  2. 指定集群中每个节点的 SSL 指纹,以确保每个节点的证书永远不会改变。 但是,你需要为每个节点执行此操作,这对于较大的集群来说在实践中是不可能的。

值得庆幸的是,作为 Python 信任存储工作的一部分,前 Elasticsearch Python 客户端维护者 Seth Larson 意识到,使用 Python 3.10+ 私有 API ,可以固定根 CA 的指纹,从而允许验证所有节点的证书,从而带来 两全其美的。 请参阅配置| Elasticsearch Python 客户端 [8.11] | Elastic?适用于 Python 客户端中有关 TLS 的所有选项。

7. options() API

在 elasticsearch-py 7.x中,客户端 API 方法中允许使用每个请求选项,例如 api_key 和 ignore。 然而,这很令人困惑,因为它混合了传输级参数和 API 级参数。 现在已弃用,因为 elasticsearch-py 8.x 引入了 options() API,转换:

client.search(index="christmas_characters", request_timeout=10)

为:

client.options(request_timeout=10).search(index="christmas_characters")

有关详细信息,请参阅迁移指南

8. 改进文档

当前的主要焦点是改进 Python 客户端的文档。

API 参考按命名空间划分,以减少类似名称的 API(如 es.existses.indices.exists)之间的混淆。

它还包括内联类型提示

最后,添加了 快速入门?交互式示例?页面。

9.无服务器 - serverless

Elastic 的最新产品 Serverless 有一个专用的 Elasticsearch Python 客户端 elasticsearch-serverless-python,其中仅包含 Serverless 支持的 API 和选项。

也就是说,默认的 Python 客户端 elasticsearch-py 也支持 Serverless,这使得你可以轻松地使用现有代码尝试 Serverless!

10. 生成式人工智能

Elastic 在 Generative AI 方面投入了大量资金,Elasticsearch 是下载次数最多的向量数据库! 最好的入门方式是 Elastic Search Labs。它包含适用于 elasticsearch-py 8.x 的每个用例的博客文章和 Python 笔记本。

就是这样! 谢谢阅读。 当你准备好升级时,迁移指南是最好的起点。

Migrating to 8.0 | Elasticsearch Python Client [8.11] | Elastic

文章来源:https://blog.csdn.net/UbuntuTouch/article/details/135475662
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。