paint-brush
Eine einfache Anleitung zum Aktualisieren von Dokumenten in Elasticsearchvon@rocksetcloud
6,608 Lesungen
6,608 Lesungen

Eine einfache Anleitung zum Aktualisieren von Dokumenten in Elasticsearch

von Rockset9m2024/04/12
Read on Terminal Reader

Zu lang; Lesen

In diesem Blog werden wichtige Strategien für den Umgang mit Updates in Elasticsearch untersucht, die für Such- und Analyseanwendungen unverzichtbar sind. Erfahren Sie mehr über vollständige Updates, Teilupdates und Skriptupdates sowie deren Auswirkungen auf die CPU-Auslastung. Entdecken Sie Alternativen wie Rockset für die effiziente Verwaltung häufiger Dokumentänderungen.
featured image - Eine einfache Anleitung zum Aktualisieren von Dokumenten in Elasticsearch
Rockset HackerNoon profile picture
0-item
1-item



Elasticsearch ist eine Open-Source-Suchmaschine und Analyse-Engine, die auf Apache Lucene basiert. Wenn Sie mit Elasticsearch Anwendungen für Change Data Capture (CDC)-Daten erstellen, sollten Sie das System so strukturieren, dass häufige Aktualisierungen oder Änderungen an den vorhandenen Dokumenten in einem Index verarbeitet werden können.


In diesem Blog gehen wir die verschiedenen verfügbaren Optionen für Updates durch, darunter vollständige Updates, Teilupdates und Skriptupdates. Wir besprechen auch, was bei der Änderung eines Dokuments in Elasticsearch im Hintergrund passiert und wie sich häufige Updates auf die CPU-Auslastung im System auswirken.

Beispielanwendung mit häufigen Updates

Um Anwendungsfälle mit häufigen Updates besser zu verstehen, sehen wir uns eine Suchanwendung für einen Video-Streaming-Dienst wie Netflix an. Wenn ein Benutzer nach einer Sendung sucht, z. B. „Polithriller“, wird ihm eine Reihe relevanter Ergebnisse basierend auf Schlüsselwörtern und anderen Metadaten angezeigt.


Schauen wir uns ein Beispieldokument der Serie „House of Cards“ in Elasticsearch an:

 { "name": "House of Cards", "description": "Frank Underwood is a Democrat appointed as the Secretary of State. Along with his wife, he sets out on a quest to seek revenge from the people who betrayed him while successfully rising to supremacy.", "genres": ["drama", "thriller"], "views": 100, }


Die Suche kann in Elasticsearch so konfiguriert werden, dass name und description als Volltextsuchfelder verwendet werden. Das Feld views , das die Anzahl der Ansichten pro Titel speichert, kann verwendet werden, um Inhalte zu verbessern und beliebtere Sendungen höher zu bewerten. Das Feld views wird jedes Mal erhöht, wenn ein Benutzer eine Episode einer Sendung oder eines Films ansieht.


Wenn Sie diese Suchkonfiguration in einer Anwendung in der Größenordnung von Netflix verwenden, kann die Anzahl der durchgeführten Aktualisierungen laut dem Netflix Engagement Report leicht Millionen pro Minute überschreiten. Dem Bericht zufolge haben sich die Benutzer von Januar bis Juli etwa 100 Milliarden Stunden an Inhalten angesehen. Bei einer angenommenen durchschnittlichen Wiedergabezeit von 15 Minuten pro Episode oder Film erreicht die Anzahl der Aufrufe pro Minute durchschnittlich 1,3 Millionen. Mit der oben angegebenen Suchkonfiguration wäre für jeden Aufruf eine Aktualisierung im Millionenbereich erforderlich.


Viele Such- und Analyseanwendungen müssen unter Umständen häufig aktualisiert werden, insbesondere wenn sie auf CDC-Daten basieren.

Durchführen von Aktualisierungen in Elasticsearch

Sehen wir uns ein allgemeines Beispiel für die Durchführung einer Aktualisierung in Elasticsearch mit dem folgenden Code an:

 - from elasticsearch import Elasticsearch # Connect to your Elasticsearch instance es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID you want to update index_name = 'movies' document_id = 'your_document_id' # Retrieve the current document to get the current 'views' value try: current_doc = es.get(index=index_name, id=document_id) current_views = current_doc['_source']['views'] except Exception as e: print(f"Error retrieving current document: {e}") current_views = 0 # Set a default value if there's an error # Define the update body to increment 'views' by 1 update_body = { "doc": { "views": current_views + 1 # Increment 'views' by 1 } } # Perform the update try: es.update(index=index_name, id=document_id, body=update_body) print("Document updated successfully!") except Exception as e: print(f"Error updating document: {e}")


Vollständige Updates im Vergleich zu teilweisen Updates in Elasticsearch

Wenn Sie in Elasticsearch eine Aktualisierung durchführen, können Sie die Index-API verwenden, um ein vorhandenes Dokument zu ersetzen, oder die Aktualisierungs-API , um eine teilweise Aktualisierung eines Dokuments vorzunehmen.


Die Index-API ruft das gesamte Dokument ab, nimmt Änderungen am Dokument vor und indexiert das Dokument dann neu. Mit der Update-API senden Sie einfach die Felder, die Sie ändern möchten, statt des gesamten Dokuments. Dadurch wird das Dokument zwar erneut indexiert, die über das Netzwerk gesendete Datenmenge wird jedoch minimiert. Die Update-API ist besonders in Fällen nützlich, in denen das Dokument groß ist und das Senden des gesamten Dokuments über das Netzwerk zeitaufwändig wäre.


Sehen wir uns an, wie die Index-API und die Update-API mit Python-Code funktionieren.

Vollständige Updates mithilfe der Index-API in Elasticsearch

 from elasticsearch import Elasticsearch # Connect to Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID index_name = "your_index" document_id = "1" # Retrieve the existing document existing_document = es.get(index=index_name, id=document_id) # Make your changes to the document existing_document["_source"]["field1"] = "new_value1" existing_document["_source"]["field2"] = "new_value2" # Call the index API to perform the full update es.index(index=index_name, id=document_id, body=existing_document["_source"])


Wie Sie im obigen Code sehen können, erfordert die Index-API zwei separate Aufrufe von Elasticsearch, was zu einer langsameren Leistung und einer höheren Belastung Ihres Clusters führen kann.


Teilaktualisierungen mithilfe der Update-API in Elasticsearch

Teilaktualisierungen verwenden intern die Reindex-API , wurden jedoch so konfiguriert, dass zur besseren Leistung nur ein einziger Netzwerkaufruf erforderlich ist.


 from elasticsearch import Elasticsearch # Connect to Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID index_name = "your_index" document_id = "1" # Specify the fields to be updated update_fields = { "field1": "new_value1", "field2": "new_value2" } # Use the update API to perform a partial update es.update(index=index_name, id=document_id, body={"doc": update_fields})


Sie können die Update-API in Elasticsearch verwenden, um die Anzahl der Aufrufe zu aktualisieren. Die Update-API allein kann jedoch nicht verwendet werden, um die Anzahl der Aufrufe basierend auf dem vorherigen Wert zu erhöhen. Das liegt daran, dass wir die ältere Anzahl der Aufrufe benötigen, um den neuen Wert für die Anzahl der Aufrufe festzulegen.


Sehen wir uns an, wie wir dies mit einer leistungsstarken Skriptsprache, Painless, beheben können.


Teilaktualisierungen mithilfe von Painless-Skripten in Elasticsearch

Painless ist eine für Elasticsearch entwickelte Skriptsprache, die für Abfrage- und Aggregationsberechnungen, komplexe Bedingungen, Datentransformationen und mehr verwendet werden kann. Painless ermöglicht auch die Verwendung von Skripten in Aktualisierungsabfragen, um Dokumente basierend auf komplexer Logik zu ändern.


Im folgenden Beispiel verwenden wir ein Painless-Skript, um ein Update in einem einzigen API-Aufruf durchzuführen und die neue Ansichtsanzahl basierend auf dem Wert der alten Ansichtsanzahl zu erhöhen.


 from elasticsearch import Elasticsearch # Connect to your Elasticsearch instance es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID you want to update index_name = 'movies' document_id = 'your_document_id' # Define the Painless script for the update update_script = { "script": { "lang": "painless", "source": "ctx._source.views += 1" # Increment 'views' by 1 } } # Perform the update using the Painless script try: es.update(index=index_name, id=document_id, body=update_script) print("Document updated successfully!") except Exception as e: print(f"Error updating document: {e}")


Das Painless-Skript ist ziemlich intuitiv zu verstehen. Es erhöht einfach die Anzahl der Aufrufe für jedes Dokument um 1.


Aktualisieren eines verschachtelten Objekts in Elasticsearch

Verschachtelte Objekte in Elasticsearch sind eine Datenstruktur, die die Indizierung von Objektarrays als separate Dokumente innerhalb eines einzelnen übergeordneten Dokuments ermöglicht. Verschachtelte Objekte sind nützlich, wenn Sie mit komplexen Daten arbeiten, die natürlich eine verschachtelte Struktur bilden, wie z. B. Objekte innerhalb von Objekten. In einem typischen Elasticsearch-Dokument werden Objektarrays abgeflacht, aber durch die Verwendung des verschachtelten Datentyps kann jedes Objekt im Array unabhängig indiziert und abgefragt werden.


Mit Painless-Skripten können auch verschachtelte Objekte in Elasticsearch aktualisiert werden.

 from elasticsearch import Elasticsearch # Connect to your Elasticsearch instance es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID for the example index_name = 'your_index' document_id = 'your_document_id' # Specify the nested field and the updated value nested_field = "nested_field_name" updated_value = "new_value" # Define the Painless script for the update update_script = { "script": { "lang": "painless", "source": "ctx._source.nested_field_name = params.updated_value", "params": { "updated_value": updated_value } } } # Perform the update using the Update API and the Painless script try: es.update(index=index_name, id=document_id, body=update_script) print("Nested object updated successfully!") except Exception as e: print(f"Error updating nested object: {e}")


Hinzufügen eines neuen Felds in Elasticsearch

Das Hinzufügen eines neuen Felds zu einem Dokument in Elasticsearch kann durch einen Indexvorgang erfolgen.


Mithilfe der Update-API können Sie ein vorhandenes Dokument teilweise mit dem neuen Feld aktualisieren. Wenn die dynamische Zuordnung im Index aktiviert ist, ist die Einführung eines neuen Felds unkompliziert. Indexieren Sie einfach ein Dokument, das dieses Feld enthält, und Elasticsearch ermittelt automatisch die geeignete Zuordnung und fügt das neue Feld der Zuordnung hinzu.


Wenn die dynamische Zuordnung im Index deaktiviert ist, müssen Sie die API zur Aktualisierung der Zuordnung verwenden. Unten sehen Sie ein Beispiel, wie Sie die Indexzuordnung aktualisieren, indem Sie dem Filmindex ein Feld „Kategorie“ hinzufügen.


 PUT /movies/_mapping { "properties": { "category": { "type": "keyword" } } }


Updates in Elasticsearch unter der Haube

Obwohl der Code einfach ist, leistet Elasticsearch intern viel Arbeit, um diese Aktualisierungen durchzuführen, da die Daten in unveränderlichen Segmenten gespeichert sind. Daher kann Elasticsearch ein Dokument nicht einfach direkt aktualisieren. Die einzige Möglichkeit, eine Aktualisierung durchzuführen, besteht darin, das gesamte Dokument neu zu indizieren, unabhängig davon, welche API verwendet wird.


Elasticsearch verwendet im Hintergrund Apache Lucene. Ein Lucene-Index besteht aus einem oder mehreren Segmenten. Ein Segment ist eine in sich geschlossene, unveränderliche Indexstruktur, die eine Teilmenge des Gesamtindex darstellt. Wenn Dokumente hinzugefügt oder aktualisiert werden, werden neue Lucene-Segmente erstellt und ältere Dokumente zum Soft-Delete markiert. Im Laufe der Zeit können sich mehrere Segmente ansammeln, wenn neue Dokumente hinzugefügt oder vorhandene aktualisiert werden. Um die Indexstruktur zu optimieren, führt Lucene kleinere Segmente regelmäßig zu größeren zusammen.

Updates sind im Wesentlichen Einfügungen in Elasticsearch

Da es sich bei jedem Aktualisierungsvorgang um einen Neuindizierungsvorgang handelt, handelt es sich bei allen Aktualisierungen im Wesentlichen um Einfügungen mit Soft-Deletes.


Das Behandeln einer Aktualisierung als Einfügevorgang hat Kostenfolgen. Einerseits bedeutet das Soft-Löschen von Daten, dass alte Daten noch einige Zeit erhalten bleiben, was den Speicher des Indexes aufbläht. Das Ausführen von Soft-Löschen, Neuindizierung und Garbage-Collection-Vorgängen belastet außerdem die CPU stark, eine Belastung, die durch das Wiederholen dieser Vorgänge auf allen Replikaten noch verschärft wird.


Updates können schwieriger werden, wenn Ihr Produkt wächst und sich Ihre Daten im Laufe der Zeit ändern. Um die Leistung von Elasticsearch aufrechtzuerhalten, müssen Sie die Shards, Analysatoren und Tokenizer in Ihrem Cluster aktualisieren, was eine Neuindizierung des gesamten Clusters erfordert. Für Produktionsanwendungen erfordert dies die Einrichtung eines neuen Clusters und die Migration aller Daten. Die Migration von Clustern ist sowohl zeitintensiv als auch fehleranfällig, daher ist sie kein Vorgang, den man auf die leichte Schulter nehmen sollte.

Updates in Elasticsearch

Die Einfachheit der Update-Operationen in Elasticsearch kann die aufwändigen operativen Aufgaben verbergen, die im Hintergrund des Systems ablaufen. Elasticsearch behandelt jedes Update als Einfügung, sodass das gesamte Dokument neu erstellt und neu indexiert werden muss. Bei Anwendungen mit häufigen Updates kann dies schnell kostspielig werden, wie wir im Netflix-Beispiel gesehen haben, wo jede Minute Millionen von Updates durchgeführt werden. Wir empfehlen, Updates entweder mithilfe der Bulk API in Batches zu verarbeiten, was zu Latenzzeiten bei Ihrer Arbeitslast führt, oder sich nach alternativen Lösungen umzusehen, wenn Sie mit häufigen Updates in Elasticsearch konfrontiert sind.


Rockset, eine in der Cloud erstellte Such- und Analysedatenbank, ist eine veränderbare Alternative zu Elasticsearch. Da Rockset auf RocksDB basiert, einem für seine Veränderlichkeit bekannten Schlüssel-Wert-Speicher, kann es Dokumente direkt aktualisieren. Dies führt dazu, dass nur der Wert einzelner Felder aktualisiert und neu indexiert wird und nicht das gesamte Dokument.


Wenn Sie die Leistung von Elasticsearch und Rockset bei aktualisierungsintensiven Workloads vergleichen möchten, können Sie eine kostenlose Testversion von Rockset mit einem Guthaben von 300 $ starten.