Auf einen Blick: ElasticSearch kann Schwierigkeiten mit verschachtelten JSON-Dokumenten haben, was zu falschen Suchergebnissen führt. Um dem entgegenzuwirken, definieren Sie den Index explizit so, dass er verschachtelte Strukturen erkennt und die Suchgenauigkeit beim Abfragen eingebetteter Dokumente verbessert.
- Verschachtelte JSON-Objekte können die Suchergebnisse in ElasticSearch verkomplizieren.
- Eine explizite Indexerstellung ist notwendig für eine genaue Abfrage eingebetteter Dokumente.
ElasticSearch ist manchmal nervig kompliziert. Man kann eine Suche ausführen, die falsche Ergebnisse anzeigt, ohne dass man darüber informiert wird. Das kann zum Beispiel passieren, wenn man ein verschachteltes JSON-Dokument hat, also ein JSON-Dokument in einem anderen. Das liegt daran, dass Lucene-Anfrage (also ElasticSearch) kein Verständnis für die Objekthierarchie in einem JSON-Dokument hat.
Das Problem bei der Suche nach verschachtelten JSON-Objekten
Um das Problem und die Lösung zu veranschaulichen, laden Sie dieses Programm massAdd.py herunter und ändern Sie die URL so, dass sie zu Ihrer ElasticSearch-Umgebung passt. Dann starten Sie es. Dann sehen Sie sich die geladenen Daten an. An den Klammern sehen Sie, dass die Klasse ein JSON-Array ist. Aber der Index, wie wir sehen werden, spiegelt das nicht wider.
curl -XGET --header 'Content-Type: application/json' http://parisx:9200/universities/_search?pretty}
"_index" : "universities",
"_type" : "universities",
"_id" : "428b71b0b935eaf58bdf874c819f263a919da5f3",
"_score" : 0.0,
"_source" : {
"firstName" : "Stephen",
"classes" : [
{
"name" : "French",
"grades" : 2
},
{
"name" : "French",
"grades" : 3
},
{
"name" : "French",
"grades" : 2
},
{
"name" : "physics",
"grades" : 6
},
{
"name" : "physics",
"grades" : 5
}
],
"lastName" : "Shakespeare",
"school" : "Arizona State University"
}
}
]
}
Beachte, dass die Indexabbildung das JSON-Array nicht anzeigt. Das liegt nicht daran, dass keine Klammern [] vorhanden sind. Vielmehr fehlt das verschachtelte Wort.
curl -XGET --header 'Content-Type: application/json' http://parisx:9200/universities?pretty
...
"classes" : {
"properties" : {
"grades" : {
"type" : "long"
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
...
Suchen Sie also nach dem, was Ihrer Meinung nach der logische Weg ist, Physikstudenten zu finden, die eine Note von 1 bekommen haben:
curl -XGET --header 'Content-Type: application/json' http://parisx:9200/universities/_search/?pretty=true -d '{
"query": {
"bool" : {
"must" : [
{ "match" : {"classes.name" : "physics"} },
{ "match" : {"classes.grades" : 1} }
]
}
}
}'
Erzeugt dieses falsche Ergebnis. Das liegt daran, dass Lucene das gesamte Dokument abflacht und sowohl Klassen als auch classes.name Physik findet.
{
"_index" : "universities",
"_type" : "universities",
"_id" : "5846c01f90d80448ab087bf4f476cd3f8ab6f683",
"_score" : 1.621972,
"_source" : {
"classes" : [
{
"grades" : 2,
"name" : "physics"
},
{
"grades" : 2,
"name" : "French"
},
{
"grades" : 3,
"name" : "physics"
},
{
"grades" : 1,
"name" : "math"
}
],
"firstName" : "Stephen",
"lastName" : "Rowe",
"school" : "University of South Carolina - Columbia"
}
}
Den Index explizit machen
Man kann einen Index in ElasticSearch einfach durch das Laden von Daten erstellen. Das erstellt ihn on-the-fly. Aber man kann nicht kontrollieren, wie der Index erstellt wird, wenn man das tut. Also machen wir die Indexerstellung explizit und stellen klar, dass Klassen ein JSON-Array sind. Löschen Sie zuerst den Index, der auch alle Daten löscht.
curl -XDELETE http://parisx:9200/universities
Erstellen Sie dann einen neuen Index und machen Sie klar, dass Klassen ein Objekt innerhalb des Universitätsobjekts sind, indem Sie "Typ" : "verschachtelt" verwenden. Hinweis: Wir füllen keine Universitätsdaten aus, sondern nur Studenten. Ignorieren Sie diese Felder. (Wir werden Universitätsdaten in einem anderen Beitrag verwenden und sie im vorherigen Beitrag verwendet).
curl -XPUT --header 'Content-Type: application/json' http://parisx:9200/universities -d '{
"mappings" : {
"universities" : {
"properties" : {
"Address" : { "type" : "text"},
"AdminEmail" : { "type" : "text"},
"AdminName" : { "type" : "text" },
"AdminPhone" : { "type" : "text" },
"DapipId" : { "type" : "text" },
"Fax" : { "type" : "text" },
"GeneralPhone" : { "type" : "text" },
"LocationName" : { "type" : "text" },
"LocationType" : { "type" : "text" },
"OpeId" : { "type" : "text" },
"ParentDapipId" : { "type" : "text" },
"ParentName" : { "type" : "text" },
"UpdateDate" : { "type" : "text" },
"classes" : {
"type" : "nested",
"properties" : {
"name" : { "type" : "text"},
"grades" : { "type" : "integer" }
}
},
"firstName" : { "type" : "text" },
"lastName" : { "type" : "text" },
"school" : { "type" : "text" }
}
}
}
}'
Dann laden Sie die Daten erneut, indem Sie massAdd.py erneut ausführen: Fügen Sie nun die verschachtelten Begriffe und den Pfad zur Abfrage hinzu, um Schüler zu finden, die in Physik eine Note von 1 erreicht haben. Der Pfad ist das Elternobjekt im JSON, das in diesem Fall Klassen ist. Und verwenden Sie classes.name, um nach Klassennamen zu suchen:
curl -XGET --header 'Content-Type: application/json' http://parisx:9200/universities/_search/?pretty=true -d '{
"query": {
"nested" : {
"path" : "classes",
"score_mode" : "avg",
"query" : {
"bool" : {
"must" : [
{ "match" : {"classes.name" : "physics"} },
{ "match" : {"classes.grades" : 1} }
]
}
}
}
}
}'
führt zum korrekten Ergebnis.
{
"_index" : "universities",
"_type" : "universities",
"_id" : "20ce682e16d0b88487addc9ceba2a695d57692aa",
"_score" : 2.188588,
"_source" : {
"lastName" : "Shakespeare",
"firstName" : "Julie",
"classes" : [
{
"grades" : 1,
"name" : "physics"
},
{
"grades" : 6,
"name" : "math"
}
],
"school" : "Arizona State University"
}
}
]
ElasticSearch-Leitfaden
- ElasticSearch Tutorial für Anfänger: ElasticSearch Grundlagen
- Verwendung von Apache Hive mit ElasticSearch
- Verwendung von ElasticSearch mit Apache Spark
- Curl ElasticSearch Befehle Spickzettel
- Spark ElasticSearch Hadoop-Update und Upsert Beispiel und Erklärung
- Wie man Apache Spark-Daten mit Python in ElasticSearch schreibt
- ElasticSearch-Suchsyntax sowie boolesche und Aggregationssuchen
- ElasticSearch verschachtelte Abfragen: Wie man nach eingebetteten Dokumenten sucht
- ElasticSearch Joins: Has_Child, Has_parent Abfrage
- Wie man einen elastischen Cluster der Version 7 einrichtet
- Wie man Filebeat für nginx und ElasticSearch konfiguriert
- Beats und Logstash verwenden, um Logs an ElasticSearch zu senden
- Wie man eine CSV-Datei mit Logstash in ElasticSearch lädt
- ElasticSearch-Aggregationen erklärt
- Was ist der ELK-Stack?
- Logstash 101: Verwendung von Logstash in einer Datenverarbeitungspipeline
- Verwendung von Kibana zur Ausführung von Abfragen in ElasticSearch mit Lucene und Kibana Query Language
- ElasticSearch Maschinelles Lernen
- Wie man Elastic Enterprise Search installiert
- Wie man Elastic Enterprise Search mit GitHub verwendet
Diese Beiträge sind meine eigenen und spiegeln nicht unbedingt die Position, Strategien oder Meinung von BMC wider.