Elasticsearch DSL es una biblioteca de alto nivel cuyo objetivo es ayudar a escribir y ejecutar consultas en Elasticsearch. Está construido sobre el cliente oficial de bajo nivel (elasticsearch-py).
Proporciona una forma más conveniente e idiomática de escribir y manipular consultas. Se mantiene cerca de Elasticsearch JSON DSL, reflejando su terminología y estructura. Expone toda la gama de DSL de Python, ya sea directamente utilizando clases definidas o expresiones similares a un conjunto de consultas.
También proporciona un contenedor opcional para trabajar con documentos como objetos Python: definir asignaciones, recuperar y guardar documentos, empaquetar los datos del documento en clases definidas por el usuario.
Para utilizar las otras API de Elasticsearch (por ejemplo, el estado del clúster), simplemente utilice el cliente subyacente.
instalación de pip elasticsearch-dsl
Consulte el directorio de ejemplos para ver algunos ejemplos complejos que utilizan elasticsearch-dsl
.
La biblioteca es compatible con todas las versiones de Elasticsearch desde 2.x
pero debes usar una versión principal coincidente :
Para Elasticsearch 8.0 y posteriores, utilice la versión principal 8 ( 8.xy
) de la biblioteca.
Para Elasticsearch 7.0 y posteriores, utilice la versión principal 7 ( 7.xy
) de la biblioteca.
Para Elasticsearch 6.0 y posteriores, utilice la versión principal 6 ( 6.xy
) de la biblioteca.
Para Elasticsearch 5.0 y posteriores, utilice la versión principal 5 ( 5.xy
) de la biblioteca.
Para Elasticsearch 2.0 y posteriores, utilice la versión principal 2 ( 2.xy
) de la biblioteca.
La forma recomendada de establecer sus requisitos en setup.py o requisitos.txt es:
# Búsqueda elástica 8.x búsqueda elástica-dsl>=8.0.0,<9.0.0 # Búsqueda elástica 7.x elasticsearch-dsl>=7.0.0,<8.0.0 # Búsqueda elástica 6.x búsqueda elástica-dsl>=6.0.0,<7.0.0 # Búsqueda elástica 5.x búsqueda elástica-dsl>=5.0.0,<6.0.0 # Búsqueda elástica 2.x búsqueda elástica-dsl>=2.0.0,<3.0.0
El desarrollo se está llevando a cabo en las ramas main
, las más antiguas solo obtienen versiones de corrección de errores.
Tengamos una solicitud de búsqueda típica escrita directamente como un 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' ])
El problema con este enfoque es que es muy detallado, propenso a errores de sintaxis como anidamiento incorrecto, difícil de modificar (por ejemplo, agregar otro filtro) y definitivamente no es divertido de escribir.
Reescribamos el ejemplo usando 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 )
Como ves, la biblioteca se encargó de:
Query
apropiados por nombre (eq. "coincidencia")bool
compuestaterm
consulta en un contexto de filtro de la consulta bool
Tengamos una clase Python simple que represente un artículo en un sistema de blogs:
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 ())
En este ejemplo puedes ver:
.save()
incorporado para conectarse al ciclo de vida de persistenciaPuede ver más en el capítulo de persistencia de la documentación.
elasticsearch-py
No es necesario portar toda la aplicación para obtener los beneficios de Python DSL; puede comenzar gradualmente creando un objeto Search
a partir de su dict
existente, modificándolo usando la API y serializándolo nuevamente 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 ()
Activar entorno virtual (virtualenvs):
$ virtualenv venv
$ source venv/bin/activate
Para instalar todas las dependencias necesarias para el desarrollo, ejecute:
$ pip install -e ' .[develop] '
Para ejecutar todas las pruebas de elasticsearch-dsl-py
, ejecute:
$ python setup.py test
Alternativamente, es posible utilizar el script run_tests.py
en test_elasticsearch_dsl
, que envuelve pytest, para ejecutar subconjuntos del conjunto de pruebas. Algunos ejemplos se pueden ver a continuación:
# 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
omitirá las pruebas de test_elasticsearch_dsl/test_integration
a menos que haya una instancia de Elasticsearch en la que pueda ocurrir una conexión. De forma predeterminada, la conexión de prueba se intenta en localhost:9200
, según los valores predeterminados especificados en la clase de conexión elasticsearch-py
. Debido a que ejecutar las pruebas de integración provocará cambios destructivos en el clúster de Elasticsearch, ejecútelas solo cuando el clúster asociado esté vacío. Como tal, si la instancia de Elasticsearch en localhost:9200
no cumple con estos requisitos, es posible especificar un servidor de prueba de Elasticsearch diferente a través de la variable de entorno TEST_ES_SERVER
.
$ TEST_ES_SERVER=my-test-server:9201 ./run_tests
La documentación está disponible en https://elasticsearch-dsl.readthedocs.io.
¿Quieres hackear Elasticsearch DSL? ¡Impresionante! Disponemos de Guía-Aporte.
Copyright 2013 Búsqueda elástica
Licenciado bajo la Licencia Apache, Versión 2.0 (la "Licencia"); no puede utilizar este archivo excepto de conformidad con la Licencia. Puede obtener una copia de la Licencia en
http://www.apache.org/licenses/LICENSE-2.0
A menos que lo exija la ley aplicable o se acuerde por escrito, el software distribuido bajo la Licencia se distribuye "TAL CUAL", SIN GARANTÍAS NI CONDICIONES DE NINGÚN TIPO, ya sean expresas o implícitas. Consulte la Licencia para conocer el idioma específico que rige los permisos y limitaciones de la Licencia.