Créer un index Elasticsearch

Les documents et les index sont deux concepts très importants dans Elasticsearch.

Un document est un ensemble de champs avec leurs valeurs associées. Pour travailler avec Elasticsearch, vous devez organiser vos données en documents, puis ajouter tous vos documents à un index. Vous pouvez considérer un index comme une collection de documents stockés dans un format hautement optimisé, conçu pour effectuer des recherches efficaces.

Si vous avez travaillé avec d'autres bases de données, vous savez peut-être que de nombreuses bases de données nécessitent une définition du schéma, qui est essentiellement une description de tous les champs que vous souhaitez stocker et de leurs types. Un index Elasticsearch peut être configuré avec un schéma si vous le souhaitez, mais il peut également dériver automatiquement le schéma à partir des données elles-mêmes. Dans cette section, vous allez laisser Elasticsearch déterminer le schéma tout seul, ce qui fonctionne assez bien pour les types de données simples comme le texte, les nombres et les dates. Plus tard, après avoir découvert des types de données plus complexes, vous apprendrez à fournir des définitions de schéma explicites.

Créer l'index

Voici comment créer un index Elasticsearch à l'aide de la bibliothèque client Python :

Dans cet exemple, self.es est une instance de la classe Elasticsearch qui, dans ce tutoriel, est stockée dans la classe Search dans search.py. Un déploiement Elasticsearch peut être utilisé pour stocker plusieurs index, chacun identifié par un nom tel que my_documents dans l'exemple ci-dessus.

Les index peuvent également être supprimés :

Si vous essayez de créer un index avec un nom qui est déjà attribué à un index existant, vous obtiendrez une erreur. Il est parfois utile de créer un index en supprimant automatiquement une instance précédente de l'index, si elle existe. Ceci est particulièrement utile lors du développement d'une application, car vous devrez probablement régénérer un index plusieurs fois.

Ajoutons une méthode d'aide create_index() dans search.py. Ouvrez ce fichier dans votre éditeur de code et ajoutez le code suivant à la fin, en laissant le contenu existant tel quel :

La méthode create_index() supprime d'abord un index portant le nom my_documents. L'option ignore_unavailable=True empêche cet appel d'échouer si le nom de l'index n'est pas trouvé. La ligne suivante de la méthode crée un nouvel index portant le même nom.

L'exemple d'application présenté dans ce tutoriel a besoin d'un seul index Elasticsearch, et pour cette raison, il code en dur le nom de l'index comme my_documents. Pour les applications plus complexes qui utilisent plusieurs index, vous pouvez envisager d'accepter le nom de l'index comme argument.

Ajouter des documents à l'index

Dans la bibliothèque client Elasticsearch pour Python, un document est représenté sous la forme d'un dictionnaire de champs clé/valeur. Les champs dont la valeur est une chaîne sont automatiquement indexés pour la recherche en texte intégral et par mot-clé, mais en plus des chaînes, vous pouvez utiliser d'autres types de champs tels que les nombres, les dates et les booléens, qui sont également indexés pour des opérations efficaces telles que le filtrage. Vous pouvez également créer des structures de données complexes dans lesquelles un champ est défini comme une liste ou un dictionnaire avec des sous-éléments.

Pour insérer un document dans un index, la méthode index() du client Elasticsearch est utilisée. Par exemple :

La valeur de retour de la méthode index() est la réponse renvoyée par le service Elasticsearch. L'information la plus importante renvoyée dans cette réponse est un élément dont le nom de clé est _id, qui représente l'identifiant unique attribué au document lorsqu'il a été inséré dans l'index. L'identifiant peut être utilisé pour récupérer, supprimer ou mettre à jour le document.

Maintenant que vous savez comment insérer un document, continuons à construire une bibliothèque d'aides utiles dans search.py, avec une nouvelle méthode insert_document() pour la classe Search. Ajoutez cette méthode au bas de search.py :

La méthode accepte le client Elasticsearch et un document de l'appelant, et insère le document dans l'index my_documents, en renvoyant la réponse du service.

NOTE: Ces opérations ne sont pas abordées dans ce tutoriel, mais le client Elasticsearch peut également modifier et supprimer des documents. Consultez la référence de la classe Elasticsearch dans la documentation de la bibliothèque Python pour en savoir plus sur toutes les opérations disponibles.

Acquisition de documents à partir d'un fichier JSON

Lors de la mise en place d'un nouvel index Elasticsearch, il est probable que vous deviez importer un grand nombre de documents. Pour ce tutoriel, le projet de démarrage comprend un fichier data.json contenant des données au format JSON. Dans cette section, vous apprendrez à importer dans l'index tous les documents contenus dans ce fichier.

La structure des documents inclus dans le fichier data.json est la suivante :

  • namele titre du document
  • urlun URL vers le document hébergé sur un site externe
  • summaryun bref résumé du contenu du document
  • contentle corps du document
  • created_onDate de création
  • updated_atdate de mise à jour (peut être absente si le document n'a jamais été mis à jour)
  • categoryla catégorie du document, qui peut être github, sharepoint ou teams
  • rolePermissionsune liste des autorisations de rôle

À ce stade, nous vous encourageons à ouvrir data.json dans votre éditeur afin de vous familiariser avec les données avec lesquelles vous allez travailler.

En fait, l'importation d'un grand nombre de documents n'est pas différente de l'importation d'un seul document à l'intérieur d'une boucle for. Pour importer tout le contenu du fichier data.json, vous pouvez faire quelque chose comme ceci :

Bien que cette approche soit efficace, elle n'est pas suffisamment évolutive. Si vous deviez insérer un très grand nombre de documents, vous devriez faire autant d'appels au service Elasticsearch. Malheureusement, chaque appel à l'API entraîne un coût de performance, et le service a également mis en place des limites de taux qui empêchent d'effectuer un grand nombre d'appels très rapidement. Pour ces raisons, il est préférable d'utiliser la fonction d'insertion en bloc du service Elasticsearch, qui permet de communiquer plusieurs opérations au service en un seul appel API.

La méthode insert_documents() présentée ci-dessous, que vous devez ajouter à la fin de search.py, utilise la méthode bulk() pour insérer tous les documents en un seul appel :

La méthode accepte une liste de documents. Au lieu d'ajouter chaque document séparément, il assemble une liste unique appelée operations, puis transmet cette liste à la méthode bulk(). Pour chaque document, deux entrées sont ajoutées à la liste operations:

  • Une description de l'opération à effectuer, fixée à index, avec le nom de l'index donné en argument.
  • Les données réelles du document

Lors du traitement d'une demande groupée, le service Elasticsearch parcourt la liste des opérations depuis le début et effectue les opérations demandées.

Régénérer l'index

Pendant que vous travaillez sur ce tutoriel, vous devrez régénérer l'index plusieurs fois. Pour simplifier cette opération, ajoutez une méthode reindex() à search.py :

Cette méthode combine les méthodes create_index() et insert_documents() créées précédemment, de sorte qu'un seul appel permet de détruire l'ancien index (s'il existe) et d'en construire un nouveau.

REMARQUE: Lors de l'indexation d'un très grand nombre de documents, il est préférable de diviser la liste des documents en ensembles plus petits et d'importer chaque ensemble séparément.

Pour faciliter l'invocation de cette méthode, nous l'exposons par le biais de la commande flask. Ouvrez app.py dans votre éditeur de code et ajoutez la fonction suivante à la fin :

Le décorateur @app.cli.command() indique au cadre Flask d'enregistrer cette fonction en tant que commande personnalisée, qui sera disponible en tant que flask reindex. Le nom de la commande est tiré du nom de la fonction, et la docstring est incluse ici parce que Flask l'utilise dans la documentation --help.

La réponse de la fonction reindex(), qui est à son tour la réponse de la méthode bulk() du client Elasticsearch, contient quelques éléments utiles qui peuvent être utilisés pour construire un message d'état agréable. En particulier, response['took'] est la durée de l'appel en millisecondes, et response['items'] est une liste des résultats individuels de chaque opération, ce qui n'est pas directement utile, mais la longueur de la liste fournit un décompte des documents insérés.

Voyez ce que cela donne en lançant flask --help à partir d'une session de terminal, en vous assurant que l'environnement virtuel Python est activé (si votre session de terminal exécute toujours l'application Flask, vous pouvez ouvrir une deuxième fenêtre de terminal). Vers la fin de l'écran d'aide, vous devriez voir l'option reindex incluse comme une commande disponible avec d'autres options fournies par le framework Flask :

Maintenant, lorsque vous voulez générer un index propre, tout ce que vous avez à faire est d'exécuter flask reindex.

Prêt à créer des expériences de recherche d'exception ?

Une recherche suffisamment avancée ne se fait pas avec les efforts d'une seule personne. Elasticsearch est alimenté par des data scientists, des ML ops, des ingénieurs et bien d'autres qui sont tout aussi passionnés par la recherche que vous. Mettons-nous en relation et travaillons ensemble pour construire l'expérience de recherche magique qui vous permettra d'obtenir les résultats que vous souhaitez.

Jugez-en par vous-même