Die Elasticsearch Query DSL verstehen

Nicht einfach von Stack Overflow kopieren, sondern verstehen, was man kopiert.

Elasticsearch ist heutzutage die Suchmaschine schlechthin, aber seine Query DSL hat eine steile Lernkurve. Als ich anfing, Elasticsearch-Abfragen zu schreiben, konnte ich durch eine Kombination aus den Elastic.co-Dokumenten und Stack Overflow etwas zusammenstellen, das funktionierte, aber ich verstand die zugrundeliegenden Konzepte hinter der Syntax nicht vollständig.

Dieses Tutorial zielt darauf ab, das zu sein, was ich gerne zuerst gelesen hätte. Es setzt voraus, dass der Leser mit den grundlegenden Konzepten von Elasticsearch vertraut ist, einfache Abfragen schreiben kann und boolesche Logik versteht. Es zielt darauf ab, dem Leser eine solide konzeptionelle Basis von Elasticsearch zu geben, bevor er versucht, die Syntax zu verstehen.

Filtern nach exakten Werten vs. volltextanalytische Suche

Ein übergreifendes Thema in Elasticsearch ist, dass alle Abfragen in drei Typen klassifiziert werden können:

1. Filtern nach exakten Werten
2. Suchen auf analysiertem Text
3. Eine Kombination aus beiden

Jedes Dokumentenfeld kann entweder als exakte Werte oder als analysierter Text (auch Volltext genannt) klassifiziert werden. Exakte Werte sind Felder wie user_iddateemail_addresses, usw. Analysierter Text sind Textdaten wie product_description oder email_body. Wie der Name schon sagt, sind diese Textdaten analysiert worden (mehr dazu später). Sie sind oft in einer natürlichen Sprache verfasst, aber nicht notwendigerweise.

Die Abfrage von Dokumenten kann durch die Angabe von Filtern über genaue Werte erfolgen. In diesen Fällen ist die Frage, ob das Dokument zurückgegeben wird, ein binäres Ja oder Nein. Ist zum Beispiel das user_id des Dokuments gleich 174517? Liegt das created_at Datum des Dokuments im Bereich des letzten Monats?

Auf der anderen Seite gibt die Abfrage von Dokumenten durch die Suche nach analysiertem Text Ergebnisse basierend auf Relevanz zurück. Ein Dokument wird nicht nach einem Ja/Nein-Kriterium zurückgegeben, sondern danach, wie relevant es ist. Wenn der analysierte Text eines Dokuments z. B. Johnny Depp enthält, sollte es auch bei Suchen nach John Depp oder Johnnie Depp zurückgegeben werden. Eine Suche nach „cook“ sollte auch Ergebnisse für „cooking“ und „cooked“ liefern.

Aus diesem Verhalten lässt sich ableiten, dass die Suche nach analysiertem Text eine hochkomplexe Operation ist und je nach Art der Textdaten unterschiedliche Analyzer-Pakete verwendet werden. Zum Beispiel sind einige Analysatorpakete sprachspezifisch, die für die Analyse von Text in einer bestimmten Sprache verwendet werden. Das Standard-Analysatorpaket ist der Standard-Analysator, der den Text nach Wortgrenzen aufteilt, Kleinbuchstaben und Interpunktion entfernt. Da die Suche nach analysiertem Text sehr viel komplizierter ist als das Filtern nach exakten Werten, ist sie sehr viel weniger performant als das Filtern nach exakten Werten. Wir werden die Suche nach analysiertem Text kurz als analysierte Suche bezeichnen.

Die Abfrage-DSL

Elasticsearch-Abfragen bestehen aus einer oder mehreren Abfrageklauseln. Abfrageklauseln können kombiniert werden, um andere Abfrageklauseln zu erstellen, die sogenannten zusammengesetzten Abfrageklauseln. Alle Abfrageklauseln haben eines dieser beiden Formate:

{
QUERY_CLAUSE: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}{
QUERY_CLAUSE: {
FIELD_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}

Die Syntax-Regel besagt, dass Abfrageklauseln wiederholt in anderen Abfrageklauseln verschachtelt werden können

{
QUERY_CLAUSE {
QUERY_CLAUSE: {
QUERY_CLAUSE: {
QUERY_CLAUSE: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}
}
}

Hier sind einige gängige Abfrageklauseln.

Match-Abfrageklausel

Die Match-Abfrageklausel ist die allgemeinste und am häufigsten verwendete Abfrageklausel. Sie ist ziemlich intelligent, denn wenn sie auf einem analysierten Textfeld ausgeführt wird, führt sie eine analysierte Suche auf dem Text durch. Wenn sie auf ein Feld mit einem exakten Wert ausgeführt wird, führt sie einen Filter durch.

Im folgenden Beispiel führt die erste Abfrageklausel eine analysierte Suche durch, da description ein analysiertes Textfeld ist. Während die zweiten beiden Abfragen Filter über exakte Wertfelder sind.

{ "match": { "description": "Fourier analysis signals processing" }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "visible": true }}

Die Match-All-Abfrageklausel

Die Match-All-Abfrageklausel gibt alle Dokumente zurück. Sie ist analog zu SELECT * FROM table in SQL.

{ "match_all": {} }

Term/Terms Abfrageklausel

Die Term- und Term-Abfrageklauseln werden verwendet, um nach einem exakten Wertefeld nach einzelnen bzw. mehreren Werten zu filtern. Bei mehreren Werten lautet die logische Verknüpfung OR.

Beispielsweise findet die erste Abfrage alle Dokumente mit dem Tag „math“. Die zweite Abfrage findet alle Dokumente mit den Tags „math“ oder „statistics“.

{ "term": { "tag": "math" }}
{ "terms": { "tag": }}

Multi-Match-Abfrageklausel

Die Multi-Match-Abfrageklausel ist eine Abgleichsabfrage, die über mehrere Felder anstelle von nur einem ausgeführt wird.

{
"multi_match": {
"query": "probability theory",
"fields":
}
}

Exists- und Missing-Filter Abfrageklausel

Der exists-Filter prüft, ob Dokumente einen Wert in einem bestimmten Feld haben. Der Missing-Filter prüft, dass Dokumente keinen Wert an einem bestimmten Feld haben. Sie sind analog zu den SQL-Klauseln IS NULL und IS NOT NULL.

{
"exists" : {
"field" : "title"
}
}

und

{
"missing" : {
"field" : "title"
}
}

Range-Filter-Abfrageklausel

Die Range-Filter-Abfrageklausel wird verwendet, um Zahlen- und Datumsfelder in Bereichen zu filtern, unter Verwendung der Operatoren gtgteltlte kurz für greater_thangreater_than_or_equalless_than und less_than_or_equal , beziehungsweise.

{ "range" : { "age" : { "gt" : 30 } } }{ 
"range": {
"born" : {
"gte": "01/01/2012",
"lte": "2013",
"format": "dd/MM/yyyy||yyyy"
}
}
}

Boolsche Abfrageklausel

Abfrageklauseln, die aus anderen Abfrageklauseln aufgebaut sind, werden zusammengesetzte Abfrageklauseln genannt. Beachten Sie, dass zusammengesetzte Abfrageklauseln auch aus anderen zusammengesetzten Abfrageklauseln bestehen können, was eine mehrschichtige Verschachtelung ermöglicht.

Die bool-Abfrageklausel ist ein Beispiel für eine zusammengesetzte Abfrageklausel, da sie verwendet wird, um mehrere Abfrageklauseln mit boolschen Operatoren zu kombinieren. Die drei unterstützten boolschen Operatoren sind mustmust_not und should , die jeweils ANDNOT , und OR entsprechen.

Angenommen, wir haben einen Index auf dem posts einer beliebten Social-Media-Seite. Hier ist eine Abfrage, um alle posts über Mathematik zu finden, die nicht wahrscheinlich ist, wo sie entweder ungelesen ist oder favorisiert wurde.

{
"bool": {
"must": { "term": { "tag": "math" }},
"must_not": { "term": { "tag": "probability" }},
"should":
}
}

Kombinieren von analysierter Suche mit Filtern

Wir haben über exakte Feldfilter und analysierte Suche in getrennten Kontexten gesprochen, aber in realen Anwendungen wollen wir die beiden oft kombinieren. Wir kombinieren analysierte Suche und exakte Feldfilter mit Hilfe der Filterklausel.

Angenommen, wir haben einen Index auf dem posts eines beliebten Webforums über Mathematik. Hier ist eine Abfrage, um alle Beiträge zu finden, indem wir eine analysierte Suche nach „Wahrscheinlichkeitstheorie“ durchführen, aber wir wollen nur posts mit 20 oder mehr Bewertungen und nicht die mit dem Tag „frequentist“.

{
"filtered": {
"query": { "match": { "body": "Probability Theory" }},
"filter": {
"bool": {
"must": {
"range": { "upvotes" : { "gt" : 20 } }
},
"must_not": { "term": { "tag": "frequentist" } }
}
}
}
}

Zusammenfassung

Der konzeptionelle Hintergrund der Elasticsearch-Abfrage-DSL ist diese Dichotomie des Filterns von Dokumenten gegenüber der Suche durch analysierten Text. Ich hoffe, Sie fanden das hilfreich.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.