# Elasticsearch: Die flexible Search Engine

Wer eine leistungsstarke Volltextsuche benötigt, wählt meist [Apache Solr](https://www.ionos.de/digitalguide/server/konfiguration/solr/). Und dieses Projekt ist auch weiterhin eine gute Wahl – doch seit 2010 bietet der Markt eine interessante Alternative: Elasticsearch. Genau wie Solr basiert auch Elasticsearch auf **[Apache Lucene](https://www.ionos.de/digitalguide/server/konfiguration/apache-lucene/)**, wartet aber mit anderen Features auf. Wir erläutern die Merkmale des Suchservers und erklären Ihnen in unserem Elasticsearch-Tutorial, wie Sie die Volltextsuche für Ihr eigenes Projekt implementieren.

Inzwischen gehört Elasticsearch zu **den wichtigsten Volltextsuchmaschinen im Internet**. Auch große Unternehmen nutzen die Software: Facebook beispielsweise arbeitet seit mehreren Jahren erfolgreich mit Elasticsearch und auch GitHub, Netflix, SoundCloud und Zalando setzen auf die erfolgreiche Suchmaschine.

## Was ist Elasticsearch?

Angesichts der Menge an Informationen auf manchen Websites lässt sich eine hohe Benutzerfreundlichkeit nur garantieren, wenn man eine funktionstüchtige Volltextsuche implementiert. Wer nicht auf Angebote von Google oder Bing zurückgreifen möchte, um seinen Besuchern eine Suchfunktion anzubieten, der muss stattdessen eine eigene Suchfunktion einbetten. Dies geht zum Beispiel mit Elasticsearch. Das **Open-Source-Projekt** basiert auf dem ebenfalls frei verfügbaren Apache Lucene.

Elasticsearch bietet die Vorteile des stabilen Vorgängers und baut diese mit weiteren Features aus. Genau wie bei Lucene funktioniert die Suche über einen Index: Statt bei einer Suchanfrage alle Dokumente zu untersuchen, überprüft das Programm einen zuvor erstellten **Index der Dokumente**, in dem alle Inhalte aufbereitet gespeichert sind. Dieser Prozess benötigt sehr viel weniger Zeit als die Suche in sämtlichen Dokumenten.

Während Sie mit Lucene vollkommen freie Hand haben, wo und wie Sie die Volltextsuche einsetzen, müssen Sie bei dieser Software allerdings vollkommen von Null anfangen. Elasticsearch ermöglicht Ihnen hingegen für den Einsatz im World Wide Web einen schnelleren Einstieg. So ist es mit Elasticsearch in kurzer Zeit möglich, **einen stabilen Suchserver** aufzubauen, der zudem noch leicht auf mehrere Maschinen verteilt werden kann.

Mehrere Knoten (verschiedene Server) schließen sich zusammen und bilden einen Cluster. Dabei kommt das sogenannte [Sharding](https://wikis.gm.fh-koeln.de/pmwiki.php/Datenbanken/Sharding "Sharding") zum Einsatz: Elasticsearch bricht hierbei den Index auf und verteilt die einzelnen Teile (shards) auf mehrere Knoten. Dadurch wird auch die Rechenlast aufgeteilt – bei großen Projekten läuft die Volltextsuche so deutlich stabiler. Für mehr Sicherheit sorgt man, indem man die Shards zusätzlich auf mehrere Knoten kopiert.

Elaticsearch basiert – genau wie Lucene – auf der objektorientierten Programmiersprache **Java**. Die Suchmaschine gibt Suchergebnisse im JSON-Format aus und liefert diese über einen REST-Webservice aus. Das [API](https://www.ionos.de/digitalguide/websites/web-entwicklung/was-ist-eine-api/ "Was ist eine API?") macht es sehr leicht, die Suchfunktion in eine Website einzubauen.

Zudem bietet Elasticsearch mit Kibana, Beats und Logstash – zusammen als **Elastic-Stack** bekannt – praktische Zusatzdienste, mit denen Sie die Volltextsuche analysieren können. Die Firma Elastic, die hinter der Entwicklung von Elasticsearch steckt und vom Erfinder des Programms gegründet wurde, bietet zudem auch kostenpflichtige Dienste an – beispielsweise Cloud-Hosting.

## Was bietet Elasticsearch, was Google &amp; Co. nicht haben?

Es gibt doch bereits Google – und dessen populäre Suchfunktion können Sie problemlos in die eigene Website integrieren. Warum also sollte man sich für den mühsameren Schritt entscheiden und eine eigene Suchmaschine mit Elasticsearch bauen? Eine mögliche Antwort: Mit Google Custom Search (GCS) machen Sie sich **abhängig vom Suchmaschinenriesen** und lassen (zumindest in der kostenlosen Version) Werbung in den Suchergebnissen zu. Das können Sie mit Elasticsearch umgehen: Der Code ist Open Source, und wenn Sie eine Volltextsuchfunktion aufgesetzt haben, gehört diese auch Ihnen – Sie sind von niemandem abhängig.

Darüber hinaus können Sie Elasticsearch ganz nach Ihren Wünschen anpassen. Wenn Sie zum Beispiel eine eigene Online-Plattform oder einen E-Shop betreiben, können Sie die Suchfunktion so einrichten, dass Sie mithilfe von Elasticsearch auch die Profile der angemeldeten Nutzer durchsuchen können. Bei solchen Anwendungsbereichen stößt GCS an seine Grenzen.

## Elasticsearch vs. Apache Solr: Was sind die wichtigsten Unterschiede?

Sowohl Elasticsearch als auch Apache Solr basieren auf Lucene, wurden aber zu eigenständigen Angeboten weiterentwickelt. Viele Nutzer fragen sich jedoch, für welches Projekt sie sich entscheiden sollten. Auch wenn Elasticsearch etwas jünger ist und im Gegensatz zu Solr nicht durch die erfahrene Apache-Community gestützt wird, hat man das Schwesterprojekt inzwischen in puncto Nutzerzahlen überholt. Grund dafür ist vor allem die **einfachere Implementierung**. Darüber hinaus ist Elasticsearch vor allem aufgrund seines **Umgangs mit dynamischen Daten** beliebt: Durch ein spezielles Caching-Verfahren schafft es Elasticsearch, dass Änderungen nicht im gesamten globalen Cache eingetragen werden müssen. Stattdessen reicht es, ein kleines Segment zu ändern. Das macht Elasticsearch flexibler.

Letzten Endes hat die Entscheidung aber oft lediglich mit den unterschiedlichen Ansätzen im Zuge von Open Source zu tun. Solr verpflichtet sich ganz dem Gedanken der Apache Software Foundation: *Community over Code*. Jeder Beitrag am Code wird ernstgenommen und die Gemeinschaft entscheidet gemeinsam, welche Ergänzungen und Weiterentwicklungen es in den finalen Code schaffen. Bei der Weiterentwicklung von Elasticsearch ist das anders: Auch dieses Projekt ist Open Source und wird unter einer freien Apache-Lizenz angeboten – allerdings bestimmt allein das Team von Elastic, welche Änderungen es in den Code schaffen. Gegen diese **Gatekeeper-Mentalität** wehren sich einige Entwickler und entscheiden sich daher für Solr.

## Elasticsearch-Tutorial

Wenn man beginnt, mit Elasticsearch zu arbeiten, sollte man sich zunächst mit einigen Grundbegriffen auseinandersetzen. So ist zum Beispiel die **Informationsstruktur** erwähnenswert:

- **Index**: Eine Suchanfrage bei Elasticsearch gilt nie den Inhalten selbst, sondern immer dem Index. In diesem sind alle Inhalte sämtlicher Dokumente gespeichert und bereits aufbereitet – dadurch erfordert die Suche nur wenig Zeit. Es handelt sich um einen sogenannten inverted index: Zu jedem Suchbegriff ist der Ort angegeben, an dem sich der Begriff finden lässt.
- **Document**: Ausgang für den Index sind die Dokumente, in denen Daten vorkommen. Sie müssen nicht zwingend vollständige Texte sein (beispielsweise Blogartikel) – es reichen bloße Dateien mit Informationen.
- **Field**: Ein Dokument wiederum besteht aus mehreren Feldern. Neben dem eigentlichen Inhaltsfeld gehören auch weitere Metadaten zu einem Dokument. So lässt sich mit Elasticsearch zum Beispiel gezielt nach Metadaten zum Autor oder zum Entstehungszeitpunkt suchen.

Übrigens: Wenn wir von Aufbereitung der Daten sprechen, geht es in erster Linie um das **Tokenizing**. Hierbei erstellt ein Algorithmus aus einem kompletten Text einzelne Begriffe. Für die Maschine gibt es erst mal so etwas wie Wörter nicht: ein Text besteht aus einer langer Zeichenfolge und ein Buchstabe hat für den Computer den gleichen Wert wie ein Leerzeichen. Damit ein Text also sinnvoll aufbereitet wird, muss dieser erst einmal in Tokens zerlegt werden. Dazu wird zum Beispiel Whitespace – also Leerzeichen und Leerzeilen – als Markierungen für Wörter angenommen. Darüber hinaus wird beim Aufbereiten auch normalisiert: Wörter werden einheitlich klein geschrieben und Satzzeichen ignoriert. Diese Methoden hat Elasticsearch alle von Apache Lucene übernommen.

Hinweis Im folgenden Tutorial arbeiten wir mit der Version 6.3.0 von Elasticsearch. Nutzen Sie eine andere Version, könnten unter Umständen einige Code-Beispiele oder Anleitungsschritte anders funktionieren.

### Installation

Die benötigten Dateien für Elasticsearch sind [frei auf der offiziellen Website von Elastic verfügbar](https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html "Liste von Installationsmöglichkeiten auf der offiziellen Homepage"). Die Dateien werden dort als **ZIP- oder tar.gz-Pakete** angeboten, weshalb sie sich unter Linux und Mac auch ganz einfach per Konsole installieren lassen.

Hinweis Elastic bietet Elasticsearch in zwei unterschiedlichen Paketen an. Die Standardversion beinhaltet auch kostenpflichtige Features, die Sie in einer Trial-Version für einige Zeit ausprobieren können. Solche Pakete hingegen, die mit OSS (Open-Source-Software) gekennzeichnet sind, enthalten ausschließlich freie Bestandteile, die unter der Lizenz Apache 2.0 veröffentlicht wurden.

Für ZIP:

```none
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-oss-6.3.0.zip
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-oss-6.3.0.zip.sha512
shasum -a 512 -c elasticsearch-oss-6.3.0.zip.sha512 
unzip elasticsearch-oss-6.3.0.zip
cd elasticsearch-6.3.0
```

Für tar.gz:

```none
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-oss-6.3.0.tar.gz
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-oss-6.3.0.tar.gz.sha512
shasum -a 512 -c elasticsearch-oss-6.3.0.tar.gz.sha512 
tar -xzf elasticsearch-oss-6.3.0.tar.gz
cd elasticsearch-6.3.0
```

Laden Sie zunächst das Paket herunter und zudem noch die **Hash-Prüfsumme** (SHA512), die Sie im dritten Schritt auch überprüfen. Anschließend entpacken Sie das Paket und wechseln in den entsprechenden Ordner.

[![Bild: Screenshot der Konsole bei der Installation von Elasticsearch](https://www.ionos.de/digitalguide/fileadmin/_processed_/3/9/csm_Elasticsearch_c86cf3f9fd.webp "Screenshot der Konsole bei der Installation von Elasticsearch")](https://www.ionos.de/digitalguide/fileadmin/DigitalGuide/Screenshots_2018/Elasticsearch.png) Screenshot der Konsole bei der Installation von Elasticsearch Das ZIP-Archiv lässt sich auch herunterladen und für die Installation unter Windows nutzen, denn in dem Paket ist eine Batch-Datei enthalten, die Sie ausführen können. Alternativ stellt Elastic inzwischen aber auch einen **MSI-Installer** zur Verfügung – dieser befindet sich allerdings noch in der Beta-Phase. Die Installationsdatei des letztgenannten enthält ein grafisches Interface, das Sie präzise durch die Installation führt.

Hinweis Da Elasticsearch auf Java basiert, muss diese Programmiersprache auch auf Ihrem System installiert sein. Laden Sie sich dafür am besten das Java Development Kit (JDK) kostenlos von der [offiziellen Website](https://www.oracle.com/de/java/technologies/downloads/ "Offizielle Website von Oracle") herunter.

Führen Sie Elasticsearch nun über die Konsole aus, indem Sie in den entsprechenden bin-Ordner navigieren und „elasticsearch“ eingeben – egal, ob unter Linux, Mac oder Windows. Öffnen Sie dann einen Browser Ihrer Wahl und rufen Sie folgenden Port des [localhost](https://www.ionos.de/digitalguide/server/knowhow/localhost/ "Localhost") auf: “**http://localhost:9200/**” Wenn Sie Elasticsearch korrekt installiert haben und auch Java richtig eingestellt ist, sollten Sie nun auf die Volltextsuche zugreifen können.

[![Bild: Anzeige der Informationen zu Elasticsearch auf dem localhost](https://www.ionos.de/digitalguide/fileadmin/_processed_/9/c/csm_Elasticsearch2_2314a0803d.webp "Anzeige der Informationen zu Elasticsearch auf dem localhost")](https://www.ionos.de/digitalguide/fileadmin/DigitalGuide/Screenshots_2018/Elasticsearch2.png) Anzeige der Informationen zu Elasticsearch auf dem localhost Mit Elasticsearch kommunizieren Sie über das REST-API, deshalb benötigen Sie zusätzlich einen entsprechenden Client. Es empfiehlt sich, hierfür **[Kibana](https://www.ionos.de/digitalguide/online-marketing/web-analyse/kibana-tutorial/)** einzusetzen (ebenfalls ein kostenfreies Open-Source-Angebot von Elastic). Mit diesem Programm können Sie Elasticsearch direkt im Browser verwenden. Dafür rufen Sie dort einfach *http://localhost:5601/* auf und können dann auf eine grafische Benutzeroberfläche zugreifen. Wie Sie Kibana richtig installieren und einrichten, erfahren Sie in unserem Tutorial zu Kibana. In Kibana und jedem anderen Client können Sie mit den HTTP-Methoden PUT, GET, POST und DELETE Kommandos an Ihre Volltextsuche senden.

### Index

In einem ersten Schritt müssen Sie zunächst Ihren Index erstellen und diesen mit Daten anfüttern. Dafür können Sie zwei verschiedenen HTTP-Methoden anwenden: **POST und PUT**. Sie benutzen PUT, wenn Sie für den Eintrag eine spezifische ID angeben möchten. Bei POST erstellt Elasticsearch selbst eine ID. In unserem Beispiel möchten wir eine Bibliografie einrichten. Jeder Eintrag soll den Namen des Autors, den Titel des Werks und das Erscheinungsjahr enthalten.

```none
POST bibliography/novels
{
"author": "Isabel Allende",
"title": "La casa de los espíritus",
"year": "1982"
}
```

Wenn Sie die Eingabe so verwenden möchten, müssen Sie die Konsole von Kibana verwenden. Falls Sie aber nicht auf diese Software zurückgreifen wollen, können Sie alternativ auch [cURL](https://www.ionos.de/digitalguide/server/tools/einstieg-in-curl-in-linux/ "Einstieg in cURL in Linux") nutzen. Statt des vorangegangen Befehls müssen Sie dann folgendes in die Kommandozeile eingeben:

```none
curl -XPOST http://localhost:9200/bibliography/novels -H "Content-Type: application/json" -d '{"author": "Isabel Allende", "title": "La casa de los espíritus", "year": "1982"}'
```

Nachfolgend zeigen wir Ihnen nur den Code für Kibana – dieser lässt sich aber problemlos in die Syntax von cURL übertragen.

Elasticsearch sollte, wenn Sie alles korrekt eingetragen haben, folgende Angaben zu Beginn der Meldung zurückgeben:

```none
{
    "_index": "bibliography",
    "_type": "novels",
    "_id": "AKKKIWQBZat9Vd0ET6N1",
    "_version": 1,
    "result": "created",
}
```

An dieser Stelle wird deutlich, dass Elasticsearch nun einen Index mit dem Namen *bibliography* und dem Typ *novels* findet. Da wir die POST-Methode verwendet haben, generierte Elasticsearch automatisch **eine einzigartige ID für unseren Eintrag**. Der Eintrag befindet sich derzeit in der ersten Version und wurde kürzlich erstellt (*created*).

Hinweis Bei einem Typ (\_type) handelte es sich in Elasticsearch früher um eine Art Unterkategorie. Über sie war es möglich, mehrere Typen unter einem Index zu versammeln. Dies führte aber zu unterschiedlichen Problemen und so plant Elastic derzeit, solche Typen nicht mehr zu nutzen. In Version 6.x ist \_type noch enthalten, es ist aber nicht mehr möglich, mehrere Typen unter einem Index zu versammeln. Ab Version 7.0 ist geplant, Typen komplett zu streichen, wie die Entwickler [in ihrem Blog erklären](https://www.elastic.co/blog/index-type-parent-child-join-now-future-in-elasticsearch "Englischer Artikel von den Entwicklern").

Sie können mit PUT Ihrem Eintrag auch **eine ganz bestimmte ID geben**. Diese wird in der ersten Zeile des Codes festgelegt. PUT benötigen Sie auch dann, wenn Sie einen bestehenden Eintrag abändern möchten.

```none
PUT bibliography/novels/1
{
"author": "William Gibson",
"title": "Neuromancer",
"year": "1984"
}
```

Der folgende Output ähnelt sehr dem, den wir auch mit der POST-Methode erhalten, allerdings gibt uns Elasticsearch die ID wieder, die wir dem Eintrag in der ersten Zeile gegeben haben. Die Reihenfolge der Angabe lautet immer ***\_index/\_type/\_id***.

```none
{
    "_index": "bibliography",
    "_type": "novels",
    "_id": "1",
    "_version": 1,
    "result": "created",
}
```

Mit dem PUT-Befehl und der eindeutigen ID können wir Einträge auch abändern:

```none
PUT bibliography/novels/1
{
"author": "William Gibson",
"title": "Count Zero",
"year": "1986"
}
```

Da der Eintrag mit der ID 1 bereits besteht, verändert Elasticsearch diesen nur, statt einen neuen zu erstellen. Das spiegelt sich auch im Output wider:

```none
{
    "_index": "bibliography",
    "_type": "novels",
    "_id": "1",
    "_version": 2,
    "result": "updated",
}
```

Die Versionsnummer ist auf 2 gestiegen und als *result* erhalten wir *updated* statt *created*. Das gleiche können Sie selbstverständlich auch mit einer zufällig von Elasticsearch erstellten ID schaffen – durch die Länge und die Unordnung der Zeichen wäre die weitere Arbeit aber um einiges umständlicher. Das Verfahren bedeutet auch, dass Elasticsearch einen Eintrag einfach überschreibt, wenn Sie beispielsweise mit den ID-Nummern durcheinander kommen. Um versehentliche Überschreibungen zu vermeiden, können Sie den ***\_create*-Endpoint** verwenden:

```none
PUT bibliography/novels/1/_create
{
"author": "Mary Shelley",
"title": "Frankenstein; or, The Modern Prometheus",
"year": "1818"
}
```

Da im Index bereits ein Eintrag mit der ID 1 vorhanden ist, bekommen Sie eine Fehlermeldung angezeigt.

[![Bild: Screenshot einer Fehlermeldung von Elasticsearch](https://www.ionos.de/digitalguide/fileadmin/_processed_/5/9/csm_Elasticsearch3_0033dba21d.webp "Screenshot einer Fehlermeldung von Elasticsearch")](https://www.ionos.de/digitalguide/fileadmin/DigitalGuide/Screenshots_2018/Elasticsearch3.png) Screenshot einer Fehlermeldung von Elasticsearch Wenn Sie Änderungen an einem Eintrag wie beschrieben vornehmen, erzeugen Sie strenggenommen einen komplett neuen Eintrag und müssen daher auch alle Angaben komplett eintragen. Stattdessen können Sie aber auch nur Veränderungen in den bestehenden Eintrag integrieren. Hierfür nutzen Sie den Endpoint ***\_update***:

```none
POST bibliography/novels/1/_update
{
"doc": {
    "author": "Franz Kafka",
"genre": "Horror"
    }
}
```

Nun haben wir dem Eintrag ein zusätzliches Feld hinzugefügt und ein bestehendes Feld verändert, ohne die anderen dabei zu löschen – allerdings nur im Vordergrund. Im Hintergrund hat Elasticsearch dennoch den kompletten Eintrag neu angelegt, dafür aber die bereits bestehenden Inhalte selbstständig eingefügt.

Prinzipiell haben wir bisher einfach einen Eintrag in eine Datenbank geschrieben und können diesen daher auch direkt wieder abrufen. Dafür verwenden wir die **GET-Methode**.

```none
GET bibliography/novels/1
```

Sie können sich den Eintrag aber auch ganz einfach im Browser anzeigen lassen:

```none
http://localhost:9200/bibliography/novels/1
```

[![Bild: Screenshot eines Eintrags in Elasticsearch](https://www.ionos.de/digitalguide/fileadmin/_processed_/a/4/csm_Elasticsearch4_960c3d579e.webp "Screenshot eines Eintrags in Elasticsearch")](https://www.ionos.de/digitalguide/fileadmin/DigitalGuide/Screenshots_2018/Elasticsearch4.png) Screenshot eines Eintrags in Elasticsearch Im Output zeigt uns Elasticsearch **alle Details unseres Eintrags**:

```none
{
    "_index": "bibliography",
    "_type": "novels",
    "_id": "1",
    "_version": 2,
    "found": true,
    "_source": {
        "author": "William Gibson",
        "title": “Count Zero",
        "year": "1984"
    }
}
```

Ergänzend zu den bereits bekannten Informationen finden Sie unter *\_source* die Felder des Dokuments. Außerdem informiert uns Elasticsearch darüber, dass tatsächlich ein Eintrag gefunden wurde. Wenn Sie versuchen, einen nicht bestehenden Eintrag aufzurufen, würde keine Fehlermeldung auftauchen. Stattdessen meldet Elasticsearch *“found”: false* und es gibt keine Einträge unter *\_source*.

Sie haben darüber hinaus auch die Möglichkeit, **nur bestimmte Informationen aus der Datenbank** zu ziehen. Nehmen wir an, Sie haben nicht nur bibliografische Daten in Ihrem Index hinterlegt, sondern auch den kompletten Text jedes aufgenommenen Romans. Auch dieser würde bei einer einfachen GET-Anfrage mitangezeigt. Nehmen wir aber an, Sie interessieren sich momentan nur für den Namen des Autors und den Titel des Werkes – dann können Sie auch gezielt nur danach fragen:

```none
GET bibliography/novels/1?_source=author,title
```

Wenn Sie die Metadaten eines Eintrags nicht interessieren, können Sie sich auch nur den Inhalt anzeigen lassen:

```none
GET bibliography/novels/1/_source
```

Nehmen wir an, Sie möchten nicht **nur einen einzelnen Eintrag** in Ihrem Index aufrufen, sondern **gleich mehrere**. Elasticsearch hat hierfür den *\_mget*-Endpoint (für multi-get) implementiert. Wenn Sie diesen nutzen, geben Sie ein **Array aus mehreren IDs** an:

```none
GET bibliography/novels/_mget
{
    "ids": ["1", "2", "3"]
}
```

Auch wenn ein Eintrag noch nicht besteht, läuft nicht die komplette Anfrage fehl. Denn alle bestehenden Daten werden Ihnen angezeigt. Was die nicht vorhandenen Daten betrifft, gibt Elasticsearch die Rückmeldung, diese nicht finden zu können.

Ganz ähnlich wie der Aufruf eines Eintrags funktioniert auch dessen Löschung. Statt mit GET arbeiten Sie allerdings mit **DELETE**:

```none
DELETE /bibliography/novels/1
```

Im folgenden Output gibt Elasticsearch Ihnen bekannt, dass es den Eintrag unter der angegebenen ID gefunden hat:

```none
{
    "_index": "bibliography",
    "_type": "novels",
    "_id": "1",
    "_version": 5,
    "result": "deleted",
}
```

Außerdem erhöht das Programm die Versionsnummer um eins. Dies hat zwei Gründe:

1. Elasticsearch markiert den Eintrag nur als gelöscht und entfernt diesen nicht direkt von der Festplatte. Erst im weiteren Verlauf der [Indexierung](https://www.ionos.de/digitalguide/online-marketing/suchmaschinenmarketing/indexierung/) wird der Eintrag verschwinden.
2. Wenn man mit verteilten Indexen auf mehreren Knoten arbeitet, ist eine detaillierte Versionsverwaltung äußerst wichtig. Deshalb markiert Elasticsearch jede Änderung als neue Version – somit auch den Löschauftrag.

Sie können Änderungen auch nur an einer bestimmten, Ihnen bekannten **Versionsnummer** durchführen. Sollte es im Cluster bereits eine neuere als die von Ihnen angegebene Version geben, führt der Änderungsversuch zu einer Fehlermeldung.

```none
PUT bibliography/novels/1?version=3
{
"author": "Marcel Proust",
"title": " À la recherche du temps perdu",
"year": "1927"
}
```

Sie können zudem nicht nur gleich mehrere Einträge auf einmal aufrufen, sondern mit *\_bulk*-Aufträgen auch mehrere erstellen oder löschen. Hierfür verwendet Elasticsearch eine etwas abgewandelte Syntax.

```none
POST bibliography/novels/_bulk
{"delete": {"_id": "1"}}
{"create": {"_id": "1"}}
{"author": "Johann Wolfgang von Goethe", "title": "Die Leiden des jungen Werther", "year": "1774"}
{"create": {"_id": "2"}}
{"author": "Umberto Eco", "title": "Il nome della rosa", "year": "1980"}
{"create": {"_id": "3"}}
{"author": "Margaret Atwood", "title": "The Handmaid’s Tale", "year": "1985"}
```

Jeder Auftrag bekommt eine eigene Zeile. Zunächst geben Sie an, welche Aktion durchgeführt werden soll (*create*, *index*, *update*, *delete*). Darüber hinaus geben Sie auch an, welchen Eintrag Sie erstellen wollen und an welchem Ort. Es ist mit einer solchen Bulk-Anweisung nämlich auch möglich, in mehreren Indexen zu arbeiten. Dafür würden Sie den Pfad nach POST leer lassen und jeder Aktion einen eigenen Pfad zuweisen. Beim Erstellen von Einträgen müssen Sie zudem – in einer neuen Zeile – einen ***request body*** angeben. In diesem steht der Inhalt des Eintrags. Die DELETE-Anweisung bedarf keines *request bodys*, da der komplette Eintrag gelöscht wird.

[![Bild: Bulk-Auftrag in Elasticsearch](https://www.ionos.de/digitalguide/fileadmin/_processed_/1/4/csm_Elasticsearch5_4eb03bf42b.webp "Bulk-Auftrag in Elasticsearch")](https://www.ionos.de/digitalguide/fileadmin/DigitalGuide/Screenshots_2018/Elasticsearch5.png) Bulk-Auftrag in Elasticsearch Bisher haben wir in den Beispielen die Inhalte stets gleich angegeben – egal, um welches Feld es sich handelte: Elasticsearch hat alle Informationen als zusammenhängende Zeichenfolge interpretiert. Doch das ist nicht immer für jedes Feld zielführend. Deshalb gibt es in Elasticsearch das **Mapping**. Dieses legt fest, wie die Algorithmen eine Eingabe zu interpretieren haben. Mit folgendem Code können Sie sich anzeigen lassen, welches Mapping derzeit in Ihrem Index eingesetzt wird:

```none
GET bibliography/novels/_mapping
```

Alle Felder werden den Typen *text* und *keyword* zugeordnet. Elasticsearch kennt **aber 6 Core Datatypes** und noch mehr spezielle Felder. Die 6 Haupttypen sind teilweise in weitere Unterkategorien untergliedert:

- **string**: Hierunter fallen sowohl *text* als auch *keyword*. Während Keywords als exakte Übereinstimmungen betrachtet werden, geht Elasticsearch bei einem Text davon aus, dass dieser analysiert werden muss, bevor man ihn benutzen kann.
- **numeric**: Elasticsearch kennt verschiedene Zahlenwerte, die sich vor allem im Umfang unterscheiden. Während zum Beispiel der Typ *byte* Werte zwischen -128 und 127 einnehmen kann, hat man bei *long* einen Spielraum von -263 bis 263-1.
- **date**: Ein Datum kann entweder tagesgenau oder mit einer Uhrzeit dazu angegeben werden. Außerdem hat man die Möglichkeit, ein Datum in Form der Unixzeit anzugeben: Sekunden oder Millisekunden seit dem 1. 1. 1970. (siehe hierzu auch [ISO 8601 für Datumsformate und Zeitangaben](https://www.ionos.de/digitalguide/websites/web-entwicklung/iso-8601/))
- **boolean**: Felder, die als *boolean* formatiert sind, können entweder einen wahren (*true*) oder einen falschen (*false*) Wert haben.
- **binary**: In solchen Feldern können Sie Binärdaten unterbringen. Um diese zu übermitteln, verwenden Sie die Base64-Kodierung.
- **range**: So geben Sie einen Bereich an. Dieser kann entweder zwischen zwei Zahlenwerten, zwei Daten oder sogar zwischen zwei IP-Adressen liegen.

Dies sind nur die Hauptkategorien, die Sie wahrscheinlich am häufigsten nutzen werden. Weitere Typen finden Sie in der [Elasticsearch-Dokumentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html "Auflistung aller Feld-Datentypen in Elasticsearch"). Die einzelnen Typen unterscheiden sich vor allem auch dahingehend, dass sie entweder *exact-value* oder *full-text* sind. Elasticsearch versteht den Inhalt des Feldes also entweder als eine genau Eingabe oder einen Inhalt, der erst verarbeitet werden muss. Im Zuge des Mappings ist nämlich auch das **Analyzing** wichtig: Das Analysieren eines Inhalts untergliedert sich wiederum in Tokenizing und Normalising:

- **Tokenizing**: Aus einem Text werden einzelne Tokens gemacht. Diese können einzelne Wörter, aber auch feststehende Begriffe aus mehreren Wörtern umfassen.
- **Normalizing**: Die Tokens werden normalisiert, indem sie alle kleingeschrieben und auf ihre Stammformen reduziert werden.

Um diesen Vorgang durchzuführen, nutzt Elasticsearch **Analyzers**. Wenn Sie ein Dokument in den Index aufnehmen und Ihr Mapping korrekt durchgeführt haben, werden alle Inhalte richtig in den invertierten Index aufgenommen. Damit Sie Mapping für sich nutzen können, müssen Sie einen komplett neuen Index erzeugen. Das Mapping von bereits existierenden Feldern ist nicht möglich.

```none
PUT bibliography
{
    "mappings": {
        "novels": {
            "properties": {
                "author": {
                    "type": "text",
                    "analyzer": "simple"
                },
                "title": {
                    "type": "text",
                    "analyzer": "standard"
                },
                "year": {
                    "type": "date",
                    "format": "year"
                }
            }
        }
}
}
```

Die beiden Felder *author* und *title* haben wir jeweils als *text* und damit als *full-text* definiert. Daher benötigen diese noch **einen passenden Analyzer**. Während wir dem Feld für den Romantitel den Standard Analyzer zur Verfügung stellen, entscheiden wir uns beim Autorennamen für den weniger komplexen Simple Analyzer. Das Erscheinungsjahr hingegen legen wir als *date* – und somit als *exact-value* – fest. Da Elasticsearch als Standardformat eine Angabe von Jahr, Monat und Tag annimmt, ändern wir das noch, da wir uns bei der Angabe nur auf das Jahr beschränken möchten.

### Suche

Im vorangegangenen Kapitel haben wir Elasticsearch und dessen Index vor allem als Datenbank genutzt. Der eigentliche Nutzen von Elasticsearch steckt allerdings in der **Volltextsuche**. Das heißt: Statt die ID eines Dokuments einzugeben und so den Eintrag aufzurufen, stellen wir Elasticsearch nun so ein, dass Sie konkret nach Inhalten suchen können. Zur Nutzung der Suchmaschine hat das Programm den *\_search*-Endpoint vorgesehen. Mit diesem in Kombination mit der GET-Methode können Sie sich zum Beispiel alle Einträge anzeigen lassen:

```none
GET bibliography/novels/_search
```

Fakt Für komplexere Suchanfragen verwendet *\_search* einen Body in geschweiften Klammern. Einige HTTP-Server sehen dies aber für die Methode GET nicht vor. Deshalb haben sich die Entwickler entschieden, dass solche Anfragen auch als POST funktionieren.

Sie können den Pfad auch frei lassen, um alle vorhandenen Indexe zu durchsuchen. Im Output finden Sie die interessanten Informationen unter *hits*:

```none
"hits": {
    "total": 3,
    "max_score": 1,
    "hits": [
        {
            "_index": "bibliography",
            "_type": "novels",
            "_id": "2",
            "_score": 1,
            "_source": {
                "author": "Umberto Eco",
                "title": "Il nome della rosa",
                "year": "1980"
            }
        },
    ],
    }
}
```

Auch alle weiteren Einträge in unserem Index werden im Output aufgeführt (und nur der Übersicht halber an dieser Stelle ausgelassen). Die Rückmeldung von Elasticsearch liefert uns neben den eigentlichen Inhalten auch zwei weitere Informationen, die uns beim Verständnis der Volltextsuche helfen können:

- **hits**: Jeder Eintrag, der den Suchkriterien entspricht, wird von Elasticsearch als Treffer gewertet. Das Programm zeigt zudem die Anzahl der *hits* an. Da sich in unserem Beispiel 3 Einträge im Index befinden und wir uns alle anzeigen lassen, gilt *“total”: 3*.
- **score**: In Form einer Punktzahl gibt Elasticsearch an, wie relevant der Eintrag in Bezug auf unsere Suchanfrage ist. Da wir in unserem Beispiel einfach nach allen Beiträgen gesucht habe, besitzen auch alle den gleichen *score* von 1. Die Einträge werden in den Suchergebnissen absteigend nach der Relevanz sortiert.

Darüber hinaus liefert Elasticsearch in der Rückmeldung noch Informationen, wie viele Shards in den Suchergebnissen involviert sind, wie viele Millisekunden die Suche gedauert hat und ob es zu einem Timeout gekommen ist.

Elasticsearch zeigt Ihnen standardmäßig nur die ersten 10 Suchergebnisse an. Sie können dies allerdings über die Einstellung von Parametern beeinflussen:

- **size**: Wie viele Ergebnisse soll Elasticsearch anzeigen?
- **from**: Wie viele Einträge soll das Programm überspringen, bevor es welche anzeigt?

Wenn Sie nun die ersten 10 Suchergebnisse gesehen hätten und sich nur noch die folgenden 15 anzeigen lassen möchten, müssen Sie eine Kombination aus beiden Parametern verwenden:

```none
GET bibliography/novels/_search?size=15&from=10
```

Elasticsearch unterscheidet zwei verschiedene Sucharten. Zum einen nutzt es eine **Lite-Version** und zum anderen eine komplexere Variante, die mit der Query DSL arbeitet – einer spezifischen Suchsprache. Bei der Lite-Version geben Sie Ihre Suchanfrage als einfachen String direkt in die Suchanfrage ein:

```none
GET bibliography/novels/_search?q=atwood
```

Sie können aber auch nur innerhalb eines bestimmten Feldes suchen:

```none
GET bibliography/novels/_search?q=author:atwood
```

Fakt Tatsächlich suchen Sie auch im ersten Beispiel in einem bestimmten Feld, ohne dieses angeben zu müssen: dem *\_all*-Feld. Wenn Sie die Inhalte eines Dokuments in Felder sortiert in den Index einfügen, erzeugt Elasticsearch im Hintergrund ein zusätzliches Feld. In diesem sind alle Inhalte aus den anderen Feldern zusätzlich gespeichert, um eine solche Suche innerhalb aller Felder zu ermöglichen.

Wenn Sie mehrere Suchkriterien miteinander kombinieren möchten, nutzen Sie dafür +. Mit dem Zeichen - schließen Sie bestimmte Kriterien aus. Wenn Sie diese **Operatoren** verwenden, müssen Sie in der Suchanfrage allerdings eine Prozentkodierung anwenden:

```none
GET bibliography/novels/_search?q=%2Bauthor%3Aatwood+%2Btitle%3Ahandmaid
```

Die **Query-String-Syntax** von Elasticsearch bietet noch mehr Feinheiten, mit denen Sie Ihre Suche anpassen können. In der [Dokumentation der Software](https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-query-string-query.html#query-string-syntax "Abschnitt über Query-String-Syntax in der offiziellen Dokumentation") haben die Entwickler von Elastic alles Wesentliche zusammengefasst: Oder-Verknüpfungen, exakte Phrasen, leere Felder oder auch Platzhalter.

Für einfache Anfragen ist diese Suchvariante gut geeignet, aber bei komplexeren Aufgaben kann das Lite-Verfahren schnell versagen: Zu groß ist die Gefahr, einen Fehler in den langen String einzutragen. Deshalb bietet Elasticsearch mit **Query DSL** ein bequemeres Verfahren. Der Ausgangspunkt einer solchen Suche ist der *query*-Parameter in Kombination mit einem *match query*:

```none
GET bibliography/novels/_search
{
    "query": {
        "match": {
"author": "allende"
}
    }
}
```

[![Bild: Beispiel einer Suche in Elasticsearch](https://www.ionos.de/digitalguide/fileadmin/_processed_/7/6/csm_Elasticsearch6_befa61433d.webp "Beispiel einer Suche in Elasticsearch")](https://www.ionos.de/digitalguide/fileadmin/DigitalGuide/Screenshots_2018/Elasticsearch6.png) Beispiel einer Suche in Elasticsearch Das Ergebnis zeigt uns alle Einträge, die im *author*-Feld den Begriff „allende“ enthalten. An ihm erkennen wir auch, dass das Analyzing im Mapping funktioniert hat, denn Elasticsearch ignoriert Groß- und Kleinschreibung. Um sich alle Einträge anzeigen zu lassen, können Sie neben der einfachen, bereits vorgestellten Variante auch *match\_all* verwenden:

```none
GET bibliography/novels/_search
{
    "query": {
        "match_all": {}
    }
}
```

Das Gegenteil dieser Suche ist *match\_none*. Elasticsearch gibt Ihnen allerdings auch die Möglichkeit, mit einem Suchbegriff in gleich mehreren Feldern zu suchen:

```none
GET bibliography/novels/_search
{
    "query": {
        "multi_match": {
            "query": "la",
            "fields": ["author", "title"]
        }
    }
}
```

Um komplexe Suchaufträge zu ermöglichen, können Sie auch mehrere Suchbegriffe miteinander kombinieren und unterschiedlich bewerten. So stehen Ihnen drei Verbindlichkeiten zur Verfügung:

- **must**: Der Begriff muss vorkommen.
- **must\_not**: Der Begriff darf nicht vorkommen.
- **should**: Wenn dieser Begriff auftaucht, wird die Relevanz in den Suchergebnissen erhöht.

In der Praxis werden Sie diese mit einer booleschen Abfrage kombinieren:

```none
GET bibliography/novels/search_
{
    "query": {
"bool": {
        "must": {
            "match": {
                "title": "la"
            }
},
        "must_not": {
            "match": {
                "title": "rabbit"
            }
        },
        "should": {
            "match": {
                "author": "allende"
            }
        }
    }
}
}
```

Erweitern können Sie Ihre Suche zudem noch, indem Sie einen Filter einbauen. Dadurch können Sie Kriterien festlegen, die die Suchergebnisse einschränken:

```none
GET bibliography/novels/search_
{
    "query": {
"bool": {
        "must": {
            "match": {
                "title": "la"
            }
},
        "filter": {
            "range": {
                "year": {
                    "gte": "1950",
                    "lt": "2000"
                }
            }
        }
    }
}
}
```

Wir haben den Filter im vorangegangen Beispiel mit einem Spektrum verknüpft: Es sollen nur die Einträge angezeigt werden, die zwischen 1950 und 2000 erschienen sind.

Fazit Mit diesem Rüstzeug haben Sie alles zur Verfügung, um die Volltextsuche für Ihr Projekt zu implementieren. Elasticsearch bietet allerdings noch weitere Methoden, mit denen Sie Ihre Suche verfeinern und komplexer gestalten können. Mehr dazu finden Sie auf der offiziellen Website von Elastic. Wenn Sie die Volltextsuche stärker erweitern möchten, können Sie auch eigene Skripte mit anderen Sprachen wie Groovy und Clojure erstellen.

## Vor- und Nachteile von Elasticsearch

Elasticsearch kann eine kraftvolle Volltextsuche sein. Man kann Elasticsearch eigentlich nur die schlechte Umsetzung des Open-Source-Gedankens vorwerfen. Ansonsten bietet die Volltextsuche zahlreiche Vorteile – auch gegenüber dem direkten Konkurrenten Apache Solr.

<table>
  <tbody>
    <tr>
      <td><strong>Vorteile</strong></td>
      <td><strong>Nachteile</strong></td>
    </tr>
    <tr>
      <td>Open Source</td>
      <td>Elastic als Gatekeeper</td>
    </tr>
    <tr>
      <td>schnell &amp; stabil</td>
      <td></td>
    </tr>
    <tr>
      <td>skalierbar</td>
      <td></td>
    </tr>
    <tr>
      <td>viele vorgefertigte Programm-Module (Analyzer, Volltextsuche …)</td>
      <td></td>
    </tr>
    <tr>
      <td>einfache Umsetzung dank Java, JSON und REST-API</td>
      <td></td>
    </tr>
    <tr>
      <td>flexibel &amp; dynamisch</td>
      <td></td>
    </tr>
  </tbody>
</table>


This is a markdown version of: [https://www.ionos.de/digitalguide/server/konfiguration/elasticsearch/](https://www.ionos.de/digitalguide/server/konfiguration/elasticsearch/) for AI/LLM consumption.