Dec 13th, 2023: [FR] 10 raisons pour demander elasticsearch-py 8.x au père Noël

This post is available in english.

En février 2022, lors de la sortie d'Elasticsearch 8.0, le client Python a également été mis à jour en version 8.0. Il s'agissait d'une réécriture partielle du client 7.x, accompagnée de nombreuses fonctionnalités intéressantes (détaillées ci-dessous), mais aussi de dépréciations et de modifications incompatibles avec le client 7.x. Actuellement, la version 7.17 du client reste relativement populaire, avec plus d'un million de téléchargements mensuels, représentant environ 50 % des téléchargements de la version 8.x.

En tant que nouveau mainteneur du client Elasticsearch Python, je souhaite que la communauté profite des améliorations que nous apportons au client en aidant tous les utilisateurs d'elasticsearch-py :

  • que ce soit aider les utilisateurs de la version 7.17 à migrer vers la version 8.x,
  • ou aider les utilisateurs de la version 8.x à profiter des nouvelles fonctionnalités.

Je sais, d'après mon expérience en tant que mainteneur d'urllib3, qu'investir dans un guide de migration vers urllib3 2.0 et aider les utilisateurs à migrer en vaut la peine. Dans le même esprit, nous essayons de rendre elasticsearch-py 8.x plus facile à utiliser en supprimant certaines dépréciations et modifications incompatibles. Ce billet met en évidence les bonnes raisons de passer à la version 8.x : celles qui étaient valables depuis près de deux ans, mais aussi les plus récentes. Et si vous êtes déjà convaincu, consultez notre guide de migration (et n'hésitez pas à nous contacter si vous rencontrez des problèmes !) :

Voici donc les dix raisons d'utiliser elasticsearch-py 8.x.

1. Disponibilité des dernières APIs Elasticsearch

Elasticsearch 8 est la meilleure version d'Elasticsearch, avec de nombreuses améliorations à tous les niveaux et une scalabilité accrue. Plus important encore pour notre discussion sur le client Python, de nombreuses nouvelles APIs ont été ajoutées :

Étant donné que le client est généré à partir de la spécification Elasticsearch, il contient toujours les dernières APIs.

2. Client Elasticsearch DSL 8.x

Le client Elasticsearch DSL est une bibliothèque de haut niveau pour écrire des requêtes plus concises. En utilisant le même index "christmas_characters" que le post du calendrier de l'Avent du 6 décembre comme exemple, cet exemple du client classique :

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

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

devient :

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

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

Vous pouvez soit adorer sa concision, soit détester de devoir apprendre un nouveau langage, mais ce client est très populaire, avec plus de 3 millions de téléchargements mensuels et une base d'utilisateurs active. Il était autrefois mal maintenu et bloqué à la version 7.4.1, mais j'ai publié la version 8.9.0 en septembre, la première compatible avec la version 8 du client Python principal.

Je suis déterminé à le maintenir à l'avenir : j'ai d'ailleurs publié la version 8.11.0 le mois dernier pour prendre en charge Python 3.12 et permettre d'écrire des collapsing queries (l'issue GitHub avait accumulé 38 votes !).

3. Annotations de type et API plus pythonique

Depuis les premiers jours du client Elasticsearch Python (en juillet 2013 !), le paramètre body est la manière de spécifier le corps des requêtes. Voici un exemple utilisant body :

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

50,
    }
)

Cependant, ce paramètre est un dictionnaire Python non typé qui n'est pas validé par le client : impossible de savoir si votre requête est correcte avant de l'envoyer au serveur. Il aurait été préférable d'identifier certains problème de bases avant d’exécuter votre code en production ! C'est pour ça qu'elasticsearch-py 8.0 a introduit une API de la spécification Elasticsearch qui fournit les types complets de chaque API. Le premier niveau des clés peut donc s'écrire avec des paramètres Python :

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

Les deux avantages immédiats sont une meilleure auto-complétion et des vérifications de typage. Par exemple, mypy générera une erreur si size n'est pas un entier. Et comme nous avons réalisé que nous pouvions unpack body paramètres typés pour tirer parti de ces avantages :

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

Nous avons décidé de déprécier complètement le paramètre body dans le cliet elasticsearch-py 8.0.

4. Réintroduction du paramètre body

Cependant, la dépréciation de body présentait les inconvénients suivants :

  • Beaucoup de code écrit au cours de la dernière décennie déclenchait désormais un deprecation warning.
  • Des paramètres inconnus tels que sub_searches ou des omissions involontaires de la spécification Elasticsearch étaient rejetés, provoquant l'échec pur et simple des requêtes et forçant inutilement l'utilisation de requêtes brutes via perform_request.
  • Des optimisations telles que le passage d'un body déjà encodé pour éviter le coût de la sérialisation JSON n'étaient plus possibles.

L'auteur original du client Python, Honza Král, a souligné ces problèmes, et nous avons décidé de permettre à body de fonctionner comme avant, sans aucun avertissement, aux côtés de la nouvelle API. Cela sera disponible dans elasticsearch-py 8.12, et j'espère que cela aidera l'adoption d'elasticsearch-py 8.x. :slight_smile:

5. Enregistrement des requêtes pour le débogage

Le client elasticsearch-py 8.x est basé sur la bibliothèque elastic-transport, qui peut être utilisée comme base pour différents clients Elastic. Cette bibliothèque a introduit une fonctionnalité très utile pour déboguer les requêtes et les réponses, activée en appelant elastic_transport.debug_logging().

import elastic_transport
from elasticsearch import Elasticsearch

# Dans cet exemple, nous déboguons un client Elasticsearch :
client = Elasticsearch(...)
# Utilisez `elastic_transport.debug_logging()` avant la requête
elastic_transport.debug_logging()

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

Le script ci-dessus produira les journaux suivants :

[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":{...}}

Dès le moment où je l'ai découverte, j'ai adopté cette fonctionnalité et elle me manque maintenant dans d'autres clients HTTP : oui, c'est pratique à ce point !

6. Épinglage de la chaîne complète de certificats SSL/TLS

Lors de la communication avec Elasticsearch via HTTPS, ce qui est le cas par défaut à partir d'Elasticsearch 8, le client doit être capable de vérifier le certificat du serveur, tout comme votre navigateur a dû vérifier le certificat de discuss.elastic.co avant de récupérer les mots que vous lisez actuellement. Cela fonctionne en suivant la chaîne de certificats jusqu'à l'autorité de certification racine. Cependant, cette autorité racine n'est pas nécessairement une autorité déjà connue fournie par exemple par Let's Encrypt, mais peut être une autorité racine spécifique à votre entreprise ou même une autorité racine générée par Elasticsearch pour un seul cluster.

Dans ces cas, il existe deux façons de vérifier le certificat :

  1. Stocker l'autorité de certification pertinente dans un fichier et configurer le paramètre ca_certs. Cependant, stocker ce fichier nécessite une étape supplémentaire, et l'accès au certificat public n'est pas toujours facile.
  2. Spécifier l'empreinte SSL de chaque nœud du cluster pour garantir que le certificat de chaque nœud ne change jamais. Cependant, il faut le faire pour chaque nœud, ce qui est impossible en pratique pour des clusters plus importants.

Heureusement, dans le cadre de son travail sur les trust stores en Python, l'ancien mainteneur du client Elasticsearch Python, Seth Larson, a réalisé qu'en utilisant des API privées Python 3.10+, il est possible d'épingler l'empreinte de l'autorité racine (et non pas d'un seul nœud), apportant le meilleur des deux mondes. Consultez Configuration | Elasticsearch Python Client [8.11] | Elastic pour voir toutes les options liées à TLS dans le client Python.

7. API options()

Dans elasticsearch-py 7.x, les options spécifiques à une requête telles que api_key et ignore font partie de chaque API. Cependant, cela mélangeait les paramètres de transport et les paramètres de l'API, ce qui était déroutant. Cela est maintenant déprécié, car elasticsearch-py 8.x a introduit l'API options(), transformant :

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

en :

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

Consultez la section .options() du guide de migration pour plus de détails.

8. Meilleure documentation

Nous concentrons en ce moment nos efforts sur la documentation du client Python.

La référence de l'API a été divisée par namespace pour réduire la confusion entre les API avec des noms identiques comme es.exists et es.indices.exists.

Elle inclut aussi des indications de typage pour chaque paramètre :

Enfin, des pages Quickstart et Exemples interactifs ont été ajoutées.

9. Serverless

La dernière offre d'Elastic, Serverless, dispose d'un client dédié Elasticsearch Python, elasticsearch-serverless-python, qui ne contient que les API et options prises en charge par Serverless.

Cela dit, les dernières versions du client Python par défaut, elasticsearch-py, prennent également en charge Serverless, ce qui facilite l'essai de Serverless avec votre code existant !

10. Intelligence artificielle générative

Elastic investit beaucoup dans l'intelligence artificielle générative, et Elasticsearch est d'ailleurs la base de données vectorielle la plus téléchargée ! La meilleure façon de commencer est Elastic Search Labs. Ce site contient des articles de blog et des notebooks Python pour chaque cas d'utilisation qui fonctionnent avec elasticsearch-py 8.x.


C'est fini ! Merci de m'avoir lu. Si vous êtes prêt à mettre à jour, le guide de migration est le meilleur endroit pour commencer :

Et si vous êtes bloqué, n'hésitez pas à poser des questions ici sur Discuss, en utilisant les tags language-clients et python. Si vous pensez avoir trouvé un bogue, veuillez ouvrir un problème sur GitHub à la place. Merci !

1 Like

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.