Kategorien
Elasticsearch

Einführung in Elasticsearch

A product could not be loaded.

Elasticsearch macht den Einstieg nicht einfach, es ist hilfreich die folgenden Begrifflichkeiten zu verstehen.

Der Analyser

Ein Analyser berechnet die Daten für den Index vor und speichert das Ergebnis beim Aktualisieren der Daten einmalig ab. Aus dieser Menge an Tokens kann dann die Suche Ergebnisse ermitteln.

Ein Analyzer besteht aus 3 Teilen, die in der Reihenfolge angewendet werden:

1. Character Filter
– html_strip: Entfernt HTML Tags and dekodiert HTML Entitäten wie zum Beispiel &
– mapping: Ersetzt jedes Vorkommen eines Strings durch einen anderen
– pattern_replace character: Ersetzt mit Hilfe eines Regex jeden Treffer durch einen geeigneten
2. Tokenizer

– Ein Tokenizer berechnet aus einem String Tokens, d.h. einzelne Wörter und Wortgruppen

3. Token Filter

– ein Token Filter kann Tokens herausfiltern, die z.B: sehr kurz sind oder bestimmte Stop-Wörter wie „der“, „es“, „am“

Es gibt auch schon vorgefertigte Analyzer für den Anfang.

Wenn nur ein Analyzer angegen wird, dann wird dieser sowohl für die Indexierung, als auch für den Query-String verwendet. Es lassen sich unterschiedliche verwenden mit Hilfe von analyzer und search_analyzer.

Mapping

Ein Mapping gehört zu jedem Index und beschreibt den Aufbau des Suchindexes. Hier werden auch festgelegt, welche Felder mit welchem Analyzer gehandhabt werden.

Mann kan für jedes Feld festlegen, welcher (Index-) Analyzer und welcher Search-Analyser benutzt werden soll und ob das Feld indexiert werden soll.

Die wichtigsten Einstellung sind der Type und die Index/Analyzer Optionen.

Folgende spezielle Werte sind möglichr:

– analyzer: keyword: es soll nur das ganze Feld in den Index und keine Abwandlungen

– index: no, bedeutet das Feld kommt nicht in den Index und ist damit nicht durchbar, aber im Ergbenis werden die Daten mitausgegeben, sinnvoll bei URLs, spart Server Ressourcen

Index und Type

Ein Index beherbergt durchsuchbare Daten und ein Type ist eine Untereinheit eines Indexes. Types desselben Indexes müssen dasselbe Mapping haben. Eltern-Kind-Beziehungen von Types gehören in denselben Index.

Ein Beispiel für verschiedene Types wäre, wenn man einen public und einen private Type deklariert. In den public Type kommen bestimmte Dokumente und in den private Type kommt eine andere (Teil) Menge. Oder in einem Shop Artikel, die man verkauft und andere, die man verleiht.

Mehr dazu hier.

Query vs. Filter

Man kann in Elasticsearch auf zwei Arten Suchen: mit einem Filter und mit einem Query. Ein Hauptunterschied ist, dass ein Filter die Dokumente nicht nach einem Score sortiert. Filter sind also am besten geeignet für Datums-Bereich (1 bis 30 Juli 2017) oder Zahlenbereiche oder auch Kategorien. Filter werden auch automatisch gecacht, auch wenn sie Teil einer Aggregation sind.

Das bedeutet, wenn man die Möglichkeit hat, Filter zu benutzen, sollte man dies auch tun. Für alle anderen Zwecke, sollte man Queries benutzen. Mehr Infos

Term Query

Ein Term Query dindet nur die exakte Übereinstimmung eines Suchbegriffes, dabei ist darauf zu achten, dass das durchsuchte Feld vorher durch einen Analyzer bei der Indexierung verändert worden ist und zum Beispiel Stop-Wörter entfernt werden wie „der“. Dann werden die ursprünglichen Ergebnisse nicht mehr gefunden, wenn man das Feld nicht auf den Typ keyword gesetzt hat.

Aggregation

Aggregationen können eine Suche hinzugefügt werden, um z.B. anzeigen zu können, wieviele der Suchergebnisse in der Kategorie X oder einen Preis unter 5€ haben.

Es sind auch verschachtelte Aggrgationen möglich, um z.B. Ergebnisse nach Kategorie und innerhalb der Kategorie nach einer Unterkategorie darzustellen.

Scripiting von Daten

Man kann die vorhanden Daten auch anpassen, um z.B. bei einem Datumsfeld den Wochentag zu berechnen und danach zu sortieren mit Hilfe verschiedener Scriptsprachen wie Groovy, Javascript und Python.

Die einfachste ist die Lucene Expression Language, mit der man einfache Berechnung schnell erledigen kann.

Es können aber auch komplexe Plugins in Java geschrieben werden, womit man die meisten Möglichkeiten hat.

Modellierung von Parent-Child Relationen

Um Relationen herzustellen und performant durchsuchen zu können, kann man Parent-Child Relationen in Elasticsearch modellieren ähnlich wie in einer relationalen Datenbank. Der Vorteil ist, dass Parent und Childs auf demselben Shard gespeichert werden und damit schnell durchsuchbar sind.

Beispiel: Auf einer Seite wie Stackoverflow hat man Fragen und Antworten, wobei die Antworten jeweils Ratings besitzen. Modellieren würde man wie folgt:

Parent: Fragen
Child: Antworten
Child von Fragen/Antworten: Ratings

Damit lassen sich dann Probleme wie:

Finden alle Antworten, die mehr als 10 Ratings haben oder

gib mir alle Antworten auf eine Frage und berechnen den Antworten Score

lösen mit Hilfe Parent-Child-Queries.

Eigenes Scoring für Dokumente (Sortierung)

Das Scoring wird standardmäßig von Elasticsearch selber vorgneommen anhand von Term-Häufigkeiten (wie oft und wo kommt das gesuchte Wort in dem Dokument vor) und relativen Term Häufigkeiten (wie oft kommt das Wort im ganzen Index vor) nach dem TF-IDF Model.

Es kann aber auch sinnvoll sein, sein eigenes Modell zu benutzen und die passenden Dokumente nach eigenen Regeln zu sortieren.

Mit dem explain Parameter lassen sich Scoring Algorithmen debuggen:

GET /my_index/doc/_search?explain
{
  "query": {
    "term": {
      "text": "fox"
    }
  }
}

In der Response ist jedes Element einzeln genau erklärt, wie es auf den eigenen Score kommt.

Anwendungsfälle: Die Ergebnismenge soll sortiert werden nach

  • die am nächsten an einem bestimmten Punkt auf der Weltkarte liegen (Geo-Koordinaten)
  • die am aktuellsten sind (Datums Feld)
  • die am nächsten an einem bestimmten Punkt auf der Weltkarte liegen und am aktuellsten sind, wobei 10km Entfernung 1 Tag Aktualität wieder gutmachen
  • Apple Laptops sollen weiter oben angeziegt werden als die von Medion
  • der Verkaufsrang und der Preis eines Artikels sollen die Position bestimmen, wobei ein Verkaufsrang von 1 – 10 einen Preisunterschied von 100€ und ein Verkaufsrang von 11- 100 einer Preisunterschied von 10€ entspricht

Dies alles lässt sich mit Hilfe eines Function Score Queries abbilden und ein paar mathematischen Überlegungen.

 Synonyme

Man betrachte einen Musik CD-Shop bei der ein Kunde nach CDs von den Rollings Stones sucht. Es wäre sehr wünschenswert, wenn er uch Ergebnisse von Mick Jagger und Keith Richards bekommt, dies kann man mit Hilfe von Synonymen bewerkstelligen.

Beispiel:

      "filter": {
        "artist_synonym" : {
          "type" : "synonym",
          "synonyms" : [
            "rolling stones, keith richards, mick jagger",
            "beatles, paul mc cartney, john lennon"
          ],
          "tokenizer": "keyword"
        }
      },