paint-brush
Un guide simple pour mettre à jour des documents dans Elasticsearchpar@rocksetcloud
6,609 lectures
6,609 lectures

Un guide simple pour mettre à jour des documents dans Elasticsearch

par Rockset9m2024/04/12
Read on Terminal Reader

Trop long; Pour lire

Ce blog explore les stratégies essentielles pour gérer les mises à jour dans Elasticsearch, vitales pour les applications de recherche et d'analyse. Découvrez les mises à jour complètes, les mises à jour partielles et les mises à jour scriptées, ainsi que leurs implications sur l'utilisation du processeur. Explorez des alternatives comme Rockset pour une gestion efficace des modifications fréquentes de documents.
featured image - Un guide simple pour mettre à jour des documents dans Elasticsearch
Rockset HackerNoon profile picture
0-item
1-item



Elasticsearch est un moteur de recherche et d'analyse open source basé sur Apache Lucene. Lorsque vous créez des applications sur des données de capture de données modifiées (CDC) à l'aide d'Elasticsearch, vous souhaiterez concevoir le système pour gérer les mises à jour ou les modifications fréquentes des documents existants dans un index.


Dans ce blog, nous passerons en revue les différentes options disponibles pour les mises à jour, notamment les mises à jour complètes, les mises à jour partielles et les mises à jour scriptées. Nous discuterons également de ce qui se passe sous le capot dans Elasticsearch lors de la modification d'un document et de l'impact de la fréquence des mises à jour sur l'utilisation du processeur dans le système.

Exemple d'application avec des mises à jour fréquentes

Pour mieux comprendre les cas d'utilisation qui nécessitent des mises à jour fréquentes , examinons une application de recherche pour un service de streaming vidéo comme Netflix. Lorsqu'un utilisateur recherche une émission, c'est-à-dire un « thriller politique », il reçoit un ensemble de résultats pertinents basés sur des mots-clés et d'autres métadonnées.


Regardons un exemple de document dans Elasticsearch de l'émission « House of Cards » :

 { "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, }


La recherche peut être configurée dans Elasticsearch pour utiliser name et description comme champs de recherche en texte intégral. Le champ views , qui stocke le nombre de vues par titre, peut être utilisé pour améliorer le contenu, en classant plus haut les émissions les plus populaires. Le champ views est incrémenté chaque fois qu'un utilisateur regarde un épisode d'une émission ou d'un film.


Lorsque vous utilisez cette configuration de recherche dans une application à l'échelle de Netflix , le nombre de mises à jour effectuées peut facilement dépasser les millions par minute, comme déterminé par le rapport d'engagement Netflix . Selon le rapport, les utilisateurs ont regardé environ 100 milliards d'heures de contenu entre janvier et juillet. En supposant une durée moyenne de visionnage de 15 minutes par épisode ou par film, le nombre de vues par minute atteint en moyenne 1,3 million. Avec la configuration de recherche spécifiée ci-dessus, chaque vue nécessiterait une mise à jour à l'échelle des millions.


De nombreuses applications de recherche et d'analyse peuvent subir des mises à jour fréquentes, en particulier lorsqu'elles sont basées sur des données CDC.

Effectuer des mises à jour dans Elasticsearch

Examinons un exemple général de la façon d'effectuer une mise à jour dans Elasticsearch avec le code ci-dessous :

 - 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}")


Mises à jour complètes et mises à jour partielles dans Elasticsearch

Lorsque vous effectuez une mise à jour dans Elasticsearch, vous pouvez utiliser l' API d'index pour remplacer un document existant ou l' API de mise à jour pour effectuer une mise à jour partielle d'un document.


L'API d'index récupère l'intégralité du document, apporte des modifications au document, puis réindexe le document. Avec l'API de mise à jour, vous envoyez simplement les champs que vous souhaitez modifier, au lieu du document entier. Cela entraîne toujours la réindexation du document mais minimise la quantité de données envoyées sur le réseau. L'API de mise à jour est particulièrement utile dans les cas où la taille du document est importante et où l'envoi de l'intégralité du document sur le réseau prendra beaucoup de temps.


Voyons comment fonctionnent l'API d'index et l'API de mise à jour à l'aide du code Python.

Mises à jour complètes à l'aide de l'API d'index dans 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"])


Comme vous pouvez le voir dans le code ci-dessus, l'API d'index nécessite deux appels distincts à Elasticsearch, ce qui peut entraîner un ralentissement des performances et une charge plus élevée sur votre cluster.


Mises à jour partielles à l'aide de l'API de mise à jour dans Elasticsearch

Les mises à jour partielles utilisent en interne l' API de réindexation , mais ont été configurées pour ne nécessiter qu'un seul appel réseau pour de meilleures performances.


 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})


Vous pouvez utiliser l'API de mise à jour dans Elasticsearch pour mettre à jour le nombre de vues, mais, à elle seule, l'API de mise à jour ne peut pas être utilisée pour incrémenter le nombre de vues en fonction de la valeur précédente. En effet, nous avons besoin de l'ancien nombre de vues pour définir la nouvelle valeur du nombre de vues.


Voyons comment résoudre ce problème à l'aide d'un langage de script puissant, Painless.


Mises à jour partielles à l'aide de scripts Painless dans Elasticsearch

Painless est un langage de script conçu pour Elasticsearch et peut être utilisé pour les calculs de requêtes et d'agrégation, les conditions complexes, les transformations de données et bien plus encore. Painless permet également d'utiliser des scripts dans les requêtes de mise à jour pour modifier des documents en fonction d'une logique complexe.


Dans l'exemple ci-dessous, nous utilisons un script Painless pour effectuer une mise à jour en un seul appel d'API et incrémenter le nouveau nombre de vues en fonction de la valeur de l'ancien nombre de vues.


 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}")


Le script Painless est assez intuitif à comprendre, il incrémente simplement le nombre de vues de 1 pour chaque document.


Mettre à jour un objet imbriqué dans Elasticsearch

Les objets imbriqués dans Elasticsearch sont une structure de données qui permet l'indexation de tableaux d'objets en tant que documents distincts au sein d'un seul document parent. Les objets imbriqués sont utiles lorsqu'il s'agit de données complexes qui forment naturellement une structure imbriquée, comme des objets dans des objets. Dans un document Elasticsearch typique, les tableaux d'objets sont aplatis, mais l'utilisation du type de données imbriqué permet à chaque objet du tableau d'être indexé et interrogé indépendamment.


Des scripts indolores peuvent également être utilisés pour mettre à jour des objets imbriqués dans Elasticsearch.

 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}")


Ajout d'un nouveau champ dans Elasticsearch

L'ajout d'un nouveau champ à un document dans Elasticsearch peut être réalisé via une opération d'indexation.


Vous pouvez mettre à jour partiellement un document existant avec le nouveau champ à l'aide de l'API de mise à jour. Lorsque le mappage dynamique sur l'index est activé, l'introduction d'un nouveau champ est simple. Indexez simplement un document contenant ce champ et Elasticsearch déterminera automatiquement le mappage approprié et ajoutera le nouveau champ au mappage.


Le mappage dynamique sur l'index étant désactivé, vous devrez utiliser l'API de mappage de mise à jour. Vous pouvez voir ci-dessous un exemple de mise à jour du mappage d'index en ajoutant un champ « catégorie » à l'index des films.


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


Mises à jour d'Elasticsearch sous le capot

Bien que le code soit simple, Elasticsearch fait en interne beaucoup de travail pour effectuer ces mises à jour, car les données sont stockées dans des segments immuables. Par conséquent, Elasticsearch ne peut pas simplement effectuer une mise à jour sur place d'un document. La seule façon d’effectuer une mise à jour est de réindexer l’intégralité du document, quelle que soit l’API utilisée.


Elasticsearch utilise Apache Lucene sous le capot. Un index Lucene est composé d'un ou plusieurs segments. Un segment est une structure d’index autonome et immuable qui représente un sous-ensemble de l’index global. Lorsque des documents sont ajoutés ou mis à jour, de nouveaux segments Lucene sont créés et les anciens documents sont marqués pour une suppression logicielle. Au fil du temps, à mesure que de nouveaux documents sont ajoutés ou que des documents existants sont mis à jour, plusieurs segments peuvent s'accumuler. Pour optimiser la structure de l'index, Lucene fusionne périodiquement des segments plus petits en segments plus grands.

Les mises à jour sont essentiellement des insertions dans Elasticsearch

Puisque chaque opération de mise à jour est une opération de réindexation, toutes les mises à jour sont essentiellement des insertions avec des suppressions logicielles.


Le fait de traiter une mise à jour comme une opération d'insertion a des implications financières. D'une part, la suppression logicielle des données signifie que les anciennes données sont encore conservées pendant un certain temps, ce qui gonfle le stockage et la mémoire de l'index. Les opérations de suppression logicielle, de réindexation et de garbage collection pèsent également lourd sur le processeur, un tribut qui est exacerbé par la répétition de ces opérations sur toutes les répliques.


Les mises à jour peuvent devenir plus délicates à mesure que votre produit se développe et que vos données évoluent au fil du temps. Pour maintenir Elasticsearch performant, vous devrez mettre à jour les fragments, les analyseurs et les tokenizers de votre cluster, ce qui nécessitera une réindexation de l'ensemble du cluster. Pour les applications de production, cela nécessitera la configuration d’un nouveau cluster et la migration de toutes les données. La migration de clusters prend du temps et est sujette aux erreurs. Ce n'est donc pas une opération à prendre à la légère.

Mises à jour dans Elasticsearch

La simplicité des opérations de mise à jour dans Elasticsearch peut masquer les lourdes tâches opérationnelles qui se déroulent sous le capot du système. Elasticsearch traite chaque mise à jour comme une insertion, nécessitant la recréation et la réindexation du document complet. Pour les applications avec des mises à jour fréquentes, cela peut vite devenir coûteux comme nous l'avons vu dans l'exemple de Netflix où des millions de mises à jour ont lieu chaque minute. Nous vous recommandons soit de regrouper les mises à jour à l'aide de l' API Bulk , qui ajoute de la latence à votre charge de travail, soit de rechercher des solutions alternatives lorsque vous êtes confronté à des mises à jour fréquentes dans Elasticsearch.


Rockset, une base de données de recherche et d'analyse construite dans le cloud, est une alternative modifiable à Elasticsearch. Construit sur RocksDB , un magasin de valeurs-clés popularisé pour sa mutabilité, Rockset peut effectuer des mises à jour sur place des documents. Cela entraîne la mise à jour et la réindexation uniquement de la valeur des champs individuels plutôt que du document entier.


Si vous souhaitez comparer les performances d'Elasticsearch et de Rockset pour les charges de travail gourmandes en mises à jour, vous pouvez démarrer un essai gratuit de Rockset avec 300 $ de crédits.