Elasticsearch DSL ist eine High-Level-Bibliothek, deren Ziel es ist, beim Schreiben und Ausführen von Abfragen für Elasticsearch zu helfen. Es basiert auf dem offiziellen Low-Level-Client (elasticsearch-py).
Es bietet eine bequemere und idiomatischere Möglichkeit, Abfragen zu schreiben und zu bearbeiten. Es bleibt nah am Elasticsearch JSON DSL und spiegelt dessen Terminologie und Struktur wider. Es stellt den gesamten DSL-Bereich von Python bereit, entweder direkt mithilfe definierter Klassen oder durch Abfragesatz-ähnliche Ausdrücke.
Es bietet außerdem einen optionalen Wrapper für die Arbeit mit Dokumenten als Python-Objekte: Definieren von Zuordnungen, Abrufen und Speichern von Dokumenten sowie Einschließen der Dokumentdaten in benutzerdefinierte Klassen.
Um die anderen Elasticsearch-APIs (z. B. Cluster-Gesundheit) zu verwenden, verwenden Sie einfach den zugrunde liegenden Client.
PIP-Installation von Elasticsearch-DSL
Im Beispielverzeichnis finden Sie einige komplexe Beispiele für die Verwendung elasticsearch-dsl
.
Die Bibliothek ist mit allen Elasticsearch-Versionen seit 2.x
kompatibel, Sie müssen jedoch eine passende Hauptversion verwenden :
Verwenden Sie für Elasticsearch 8.0 und höher die Hauptversion 8 ( 8.xy
) der Bibliothek.
Verwenden Sie für Elasticsearch 7.0 und höher die Hauptversion 7 ( 7.xy
) der Bibliothek.
Verwenden Sie für Elasticsearch 6.0 und höher die Hauptversion 6 ( 6.xy
) der Bibliothek.
Verwenden Sie für Elasticsearch 5.0 und höher die Hauptversion 5 ( 5.xy
) der Bibliothek.
Verwenden Sie für Elasticsearch 2.0 und höher die Hauptversion 2 ( 2.xy
) der Bibliothek.
Die empfohlene Methode zum Festlegen Ihrer Anforderungen in Ihrer setup.py oder require.txt ist:
# Elasticsearch 8.x elasticsearch-dsl>=8.0.0,<9.0.0 # Elasticsearch 7.x elasticsearch-dsl>=7.0.0,<8.0.0 # Elasticsearch 6.x elasticsearch-dsl>=6.0.0,<7.0.0 # Elasticsearch 5.x elasticsearch-dsl>=5.0.0,<6.0.0 # Elasticsearch 2.x elasticsearch-dsl>=2.0.0,<3.0.0
Die Entwicklung findet im main
statt, ältere Zweige erhalten nur Bugfix-Releases
Lassen Sie uns eine typische Suchanfrage direkt als dict
schreiben:
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' ])
Das Problem bei diesem Ansatz besteht darin, dass er sehr ausführlich ist, anfällig für Syntaxfehler wie falsche Verschachtelung, schwer zu ändern ist (z. B. durch Hinzufügen eines weiteren Filters) und definitiv keinen Spaß beim Schreiben macht.
Schreiben wir das Beispiel mit der Python-DSL um:
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 )
Wie Sie sehen, hat sich die Bibliothek um Folgendes gekümmert:
Query
nach Namen (z. B. „Match“)bool
-Abfrageterm
in einen Filterkontext der bool
-AbfrageLassen Sie uns eine einfache Python-Klasse haben, die einen Artikel in einem Blogging-System darstellt:
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 ())
In diesem Beispiel sehen Sie:
.save()
Methode, um sich in den Persistenzlebenszyklus einzubindenWeitere Informationen finden Sie im Kapitel „Persistenz“ der Dokumentation.
elasticsearch-py
Sie müssen nicht Ihre gesamte Anwendung portieren, um die Vorteile des Python-DSL zu nutzen. Sie können schrittweise beginnen, indem Sie ein Search
aus Ihrem vorhandenen dict
erstellen, es mithilfe der API ändern und es wieder in ein dict
serialisieren:
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 ()
Virtuelle Umgebung aktivieren (virtualenvs):
$ virtualenv venv
$ source venv/bin/activate
Führen Sie Folgendes aus, um alle für die Entwicklung erforderlichen Abhängigkeiten zu installieren:
$ pip install -e ' .[develop] '
Um alle Tests für elasticsearch-dsl-py
auszuführen, führen Sie Folgendes aus:
$ python setup.py test
Alternativ ist es möglich, das Skript run_tests.py
in test_elasticsearch_dsl
zu verwenden, das pytest umschließt, um Teilmengen der Testsuite auszuführen. Einige Beispiele sind unten zu sehen:
# 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
überspringt Tests von test_elasticsearch_dsl/test_integration
es sei denn, es gibt eine Instanz von Elasticsearch, auf der eine Verbindung hergestellt werden kann. Standardmäßig wird die Testverbindung bei localhost:9200
versucht, basierend auf den in der elasticsearch-py
-Verbindungsklasse angegebenen Standardwerten. Da die Ausführung der Integrationstests destruktive Änderungen am Elasticsearch-Cluster zur Folge hat, führen Sie sie nur aus, wenn der zugehörige Cluster leer ist. Wenn die Elasticsearch-Instanz unter localhost:9200
diese Anforderungen nicht erfüllt, ist es daher möglich, über die Umgebungsvariable TEST_ES_SERVER
einen anderen Test-Elasticsearch-Server anzugeben.
$ TEST_ES_SERVER=my-test-server:9201 ./run_tests
Die Dokumentation ist unter https://elasticsearch-dsl.readthedocs.io verfügbar.
Möchten Sie Elasticsearch DSL hacken? Eindrucksvoll! Wir haben einen Beitragsleitfaden.
Copyright 2013 Elasticsearch
Lizenziert unter der Apache-Lizenz, Version 2.0 (die „Lizenz“); Sie dürfen diese Datei nur in Übereinstimmung mit der Lizenz verwenden. Eine Kopie der Lizenz erhalten Sie unter
http://www.apache.org/licenses/LICENSE-2.0
Sofern nicht durch geltendes Recht vorgeschrieben oder schriftlich vereinbart, wird die im Rahmen der Lizenz vertriebene Software „WIE BESEHEN“ und OHNE GEWÄHRLEISTUNGEN ODER BEDINGUNGEN JEGLICHER ART, weder ausdrücklich noch stillschweigend, vertrieben. Die spezifische Sprache, die die Berechtigungen und Einschränkungen im Rahmen der Lizenz regelt, finden Sie in der Lizenz.