Elasticsearch DSL est une bibliothèque de haut niveau dont le but est d'aider à l'écriture et à l'exécution de requêtes sur Elasticsearch. Il est construit sur le client officiel de bas niveau (elasticsearch-py).
Il fournit un moyen plus pratique et idiomatique d’écrire et de manipuler des requêtes. Il reste proche du DSL Elasticsearch JSON, reflétant sa terminologie et sa structure. Il expose toute la gamme du DSL de Python soit directement en utilisant des classes définies, soit des expressions de type ensemble de requêtes.
Il fournit également un wrapper facultatif pour travailler avec des documents en tant qu'objets Python : définir des mappages, récupérer et enregistrer des documents, encapsuler les données du document dans des classes définies par l'utilisateur.
Pour utiliser les autres API Elasticsearch (par exemple, la santé du cluster), utilisez simplement le client sous-jacent.
pip installer elasticsearch-dsl
Veuillez consulter le répertoire d'exemples pour voir quelques exemples complexes utilisant elasticsearch-dsl
.
La bibliothèque est compatible avec toutes les versions d'Elasticsearch depuis 2.x
mais vous devez utiliser une version majeure correspondante :
Pour Elasticsearch 8.0 et versions ultérieures, utilisez la version majeure 8 ( 8.xy
) de la bibliothèque.
Pour Elasticsearch 7.0 et versions ultérieures, utilisez la version majeure 7 ( 7.xy
) de la bibliothèque.
Pour Elasticsearch 6.0 et versions ultérieures, utilisez la version majeure 6 ( 6.xy
) de la bibliothèque.
Pour Elasticsearch 5.0 et versions ultérieures, utilisez la version majeure 5 ( 5.xy
) de la bibliothèque.
Pour Elasticsearch 2.0 et versions ultérieures, utilisez la version majeure 2 ( 2.xy
) de la bibliothèque.
La méthode recommandée pour définir vos exigences dans votre fichier setup.py ou conditions.txt est la suivante :
# Elasticsearch 8.x élastiquesearch-dsl>=8.0.0,<9.0.0 # Elasticsearch 7.x élastiquesearch-dsl>=7.0.0,<8.0.0 # Elasticsearch 6.x élastiquesearch-dsl>=6.0.0,<7.0.0 # Elasticsearch 5.x élastiquesearch-dsl>=5.0.0,<6.0.0 # Elasticsearch 2.x élastiquesearch-dsl>=2.0.0,<3.0.0
Le développement se déroule sur main
, les anciennes branches ne reçoivent que des versions de correction de bugs.
Prenons une requête de recherche typique écrite directement sous forme de dict
:
from elasticsearch import Elasticsearch
client = Elasticsearch ( "https://localhost:9200" )
response = client . search (
index = "my-index" ,
body = {
"query" : {
"bool" : {
"must" : [{ "match" : { "title" : "python" }}],
"must_not" : [{ "match" : { "description" : "beta" }}],
"filter" : [{ "term" : { "category" : "search" }}]
}
},
"aggs" : {
"per_tag" : {
"terms" : { "field" : "tags" },
"aggs" : {
"max_lines" : { "max" : { "field" : "lines" }}
}
}
}
}
)
for hit in response [ 'hits' ][ 'hits' ]:
print ( hit [ '_score' ], hit [ '_source' ][ 'title' ])
for tag in response [ 'aggregations' ][ 'per_tag' ][ 'buckets' ]:
print ( tag [ 'key' ], tag [ 'max_lines' ][ 'value' ])
Le problème avec cette approche est qu'elle est très verbeuse, sujette à des erreurs de syntaxe comme une imbrication incorrecte, difficile à modifier (par exemple en ajoutant un autre filtre) et certainement pas amusante à écrire.
Réécrivons l'exemple en utilisant le Python DSL :
from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search
client = Elasticsearch ( "https://localhost:9200" )
s = Search ( using = client , index = "my-index" )
. filter ( "term" , category = "search" )
. query ( "match" , title = "python" )
. exclude ( "match" , description = "beta" )
s . aggs . bucket ( 'per_tag' , 'terms' , field = 'tags' )
. metric ( 'max_lines' , 'max' , field = 'lines' )
response = s . execute ()
for hit in response :
print ( hit . meta . score , hit . title )
for tag in response . aggregations . per_tag . buckets :
print ( tag . key , tag . max_lines . value )
Comme vous le voyez, la bibliothèque s'est occupée de :
Query
appropriés par nom (eq. "match")bool
composéeterm
requête dans un contexte de filtre de la requête bool
Prenons une simple classe Python représentant un article dans un système de blog :
from datetime import datetime
from elasticsearch_dsl import Document , Date , Integer , Keyword , Text , connections
# Define a default Elasticsearch client
connections . create_connection ( hosts = "https://localhost:9200" )
class Article ( Document ):
title = Text ( analyzer = 'snowball' , fields = { 'raw' : Keyword ()})
body = Text ( analyzer = 'snowball' )
tags = Keyword ()
published_from = Date ()
lines = Integer ()
class Index :
name = 'blog'
settings = {
"number_of_shards" : 2 ,
}
def save ( self , ** kwargs ):
self . lines = len ( self . body . split ())
return super ( Article , self ). save ( ** kwargs )
def is_published ( self ):
return datetime . now () > self . published_from
# create the mappings in elasticsearch
Article . init ()
# create and save and article
article = Article ( meta = { 'id' : 42 }, title = 'Hello world!' , tags = [ 'test' ])
article . body = ''' looong text '''
article . published_from = datetime . now ()
article . save ()
article = Article . get ( id = 42 )
print ( article . is_published ())
# Display cluster health
print ( connections . get_connection (). cluster . health ())
Dans cet exemple, vous pouvez voir :
.save()
pour se connecter au cycle de vie de persistanceVous pouvez en voir plus dans le chapitre sur la persistance de la documentation.
elasticsearch-py
Vous n'avez pas besoin de porter l'intégralité de votre application pour bénéficier des avantages du Python DSL, vous pouvez commencer progressivement en créant un objet Search
à partir de votre dict
existant, en le modifiant à l'aide de l'API et en le sérialisant en un dict
:
body = {...} # insert complicated query here
# Convert to Search object
s = Search . from_dict ( body )
# Add some filters, aggregations, queries, ...
s . filter ( "term" , tags = "python" )
# Convert back to dict to plug back into existing code
body = s . to_dict ()
Activer l'environnement virtuel (virtualenvs) :
$ virtualenv venv
$ source venv/bin/activate
Pour installer toutes les dépendances nécessaires au développement, exécutez :
$ pip install -e ' .[develop] '
Pour exécuter tous les tests pour elasticsearch-dsl-py
, exécutez :
$ python setup.py test
Alternativement, il est possible d'utiliser le script run_tests.py
dans test_elasticsearch_dsl
, qui encapsule pytest, pour exécuter des sous-ensembles de la suite de tests. Quelques exemples peuvent être vus ci-dessous :
# Run all of the tests in `test_elasticsearch_dsl/test_analysis.py`
$ ./run_tests.py test_analysis.py
# Run only the `test_analyzer_serializes_as_name` test.
$ ./run_tests.py test_analysis.py::test_analyzer_serializes_as_name
pytest
ignorera les tests de test_elasticsearch_dsl/test_integration
sauf s'il existe une instance d'Elasticsearch sur laquelle une connexion peut se produire. Par défaut, la connexion test est tentée sur localhost:9200
, en fonction des valeurs par défaut spécifiées dans la classe de connexion elasticsearch-py
. Étant donné que l'exécution des tests d'intégration entraînera des modifications destructrices du cluster Elasticsearch, exécutez-les uniquement lorsque le cluster associé est vide. Ainsi, si l'instance Elasticsearch sur localhost:9200
ne répond pas à ces exigences, il est possible de spécifier un autre serveur Elasticsearch de test via la variable d'environnement TEST_ES_SERVER
.
$ TEST_ES_SERVER=my-test-server:9201 ./run_tests
La documentation est disponible sur https://elasticsearch-dsl.readthedocs.io.
Vous voulez pirater Elasticsearch DSL ? Génial! Nous avons un guide de contribution.
Copyright 2013 Elasticsearch
Sous licence Apache, version 2.0 (la « Licence » ); vous ne pouvez pas utiliser ce fichier sauf en conformité avec la licence. Vous pouvez obtenir une copie de la licence à
http://www.apache.org/licenses/LICENSE-2.0
Sauf disposition contraire de la loi applicable ou accord écrit, le logiciel distribué sous la licence est distribué « EN L'ÉTAT », SANS GARANTIE OU CONDITION D'AUCUNE SORTE, expresse ou implicite. Consultez la licence pour connaître la langue spécifique régissant les autorisations et les limitations en vertu de la licence.