Chapitre 2. Immersion dans l’outil

Ce chapitre couvre:

  • Définition de documents, types et index
  • Compréhension des nœuds Elasticsearch, des fragments primaires et des répliques
  • Indexer des documents avec CURL et un ensemble de données
  • Recherche et récupération de données
  • Définition des options de configuration Elasticsearch
  • Travailler avec plusieurs nœuds

Maintenant que vous connaissez un peu plus sur le moteur de recherche Elasticsearch, et que je vous ai présenté certaines de ses principales caractéristiques au chapitre 1, passons maintenant à l’aspect pratique. Voyons ce qu’il fait et comment il le fait. Imaginez que vous soyez chargé de créer un moyen de rechercher dans des millions de documents, comme un site Web qui permet aux utilisateurs de créer des groupes d’intérêts communs et de se réunir. Dans ce cas, les documents peuvent être des groupes de rencontre(get-together groups), des événements individuels. Vous devez implémenter votre solution de façon à ce quelle soit tolérante aux pannes (donc robuste) et votre configuration doit être en mesure de prendre en charge davantage de données et davantage de recherches simultanées, à mesure que votre site de rencontre connait de plus en plus de succès.

Dans ce chapitre, je vais vous montrer comment gérer un tel scénario en expliquant comment les données Elasticsearch sont organisées. Ensuite, vous commencerez à indexer et rechercher des données réelles pour un site Web de rencontre à l’aide des exemples de code fournis pour ce chapitre. Nous allons utiliser cet exemple et les exemples de code tout au long du livre pour vous permettre de faire de vraies recherches et veritablement decouvrir les méchanismes d’indexation.

Toutes les opérations seront effectuées à l’aide de CURL, un joli petit outil de ligne de commande pour les requêtes HTTP. Plus tard, vous pourrez remplacer cURL par un autre outil si vous vous sentez le besoin. Vers la fin du chapitre, vous apporterez des modifications à la configuration et démarrerez de nouvelles instances d’Elasticsearch. Vous pourrez ainsi expérimenter un cluster de plusieurs noeuds.

Nous allons commencer avec l’organisation des données. Pour comprendre la manière dont les données sont organisées dans Elasticsearch, nous allons l’analyser sous deux angles:

  • Disposition logique: ce que votre application de recherche doit connaître. L’unité que vous utiliserez pour l’indexation et la recherche est un document, que vous pouvez considérer comme une ligne dans une base de données relationnelle. Les documents sont regroupés en types, qui contiennent des documents de la même manière que les tableaux contiennent des lignes. Enfin, un ou plusieurs types résident dans un index, le plus grand conteneur, similaire à une base de données dans le monde SQL.
  • Disposition physique – Comment Elasticsearch traite vos données en arrière-plan. Elasticsearch divise chaque index en fragments, qui peuvent migrer entre les serveurs composant un cluster. En général, les applications ne s’inquiètent pas de cela, car elles fonctionnent avec Elasticsearch de la même manière, qu’il s’agisse d’un ou de plusieurs serveurs. Toutefois, lorsque vous administrez le cluster, vous vous en inquiéterez, car la façon dont vous configurez la présentation physique déterminera ses performances, son évolutivité et sa disponibilité.

La figure 2.1 illustre les deux perspectives.

Commençons par la disposition logique, ou ce que voit l’application.

2.1. COMPRENDRE LA DISPOSITION LOGIQUE: DOCUMENTS, TYPES ET INDICES

Lorsque vous indexez un document dans Elasticsearch, vous le mettez dans un type dans un index. Sur la figure 2.2, l’index get-together contient deux types: événement et groupe.



L’identifiant ne doit pas obligatoirement être un entier. En fait, il s’agit d’une chaîne, et il n’existe aucune contrainte. Vous pouvez y indiquer ce qui convient à votre application.



La combinaison index-type-ID identifie de manière unique un document dans votre configuration Elasticsearch. Lorsque vous effectuez une recherche, vous pouvez rechercher des documents dans ce type spécifique, dans cet index spécifique ou dans plusieurs types, voire plusieurs index.

À ce stade, vous pourriez vous demander: que sont exactement un document, un type et un index? C’est exactement ce dont nous allons discuter ensuite.

2.1.1. Les documents

Nous avons indiqué au chapitre 1 qu’Elasticsearch était orienté document, ce qui signifie que la plus petite unité de données que vous indexez ou recherchez est un document. Un document a quelques propriétés importantes dans Elasticsearch:

  • Il est autonome. Un document contient à la fois les champs (nom) et leurs valeurs (Elasticsearch Denver).
  • Cela peut être hiérarchique. Pensez à cela comme des documents dans des documents. La valeur d’un champ peut être simple, comme une chaîne de caractères. Elle peut également contenir d’autres champs et valeurs. Par exemple, le champ de localisation peut contenir à la fois une ville et une adresse.
  • Il a une structure flexible. Vos documents ne dépendent pas d’un schéma prédéfini. Par exemple, tous les événements n’ont pas besoin de valeurs de description, de sorte que ce champ puisse être complètement omis. Mais cela peut nécessiter de nouveaux champs, tels que la latitude et la longitude de l’emplacement.

Un document est normalement une représentation JSON de vos données. Comme nous l’avons vu au chapitre 1, le format JSON est le moyen de communication le plus utilisé avec Elasticsearch. Il s’agit de la méthode que nous utiliserons tout au long du livre. Par exemple, un événement de votre site de rencontre peut être représenté par le document suivant:



Tout au long du livre, nous utiliserons différentes couleurs pour les noms de champs et les valeurs des documents JSON afin de faciliter leur lecture. Les noms de champ sont plus foncés / bleus et les valeurs plus claires / rouges.

 



Vous pouvez également imaginer une table avec trois colonnes: nom, organisateur et emplacement. Le document serait une ligne contenant les valeurs. Mais il y a quelques différences qui rendent cette comparaison inexacte. Une différence est que, contrairement aux lignes, les documents peuvent être hiérarchiques. Par exemple, l’emplacement peut contenir un nom et une géolocalisation:

Un seul document peut également contenir des tableaux de valeurs; par exemple:

Les documents dans Elasticsearch sont supposés être sans schéma, en ce sens que tous vos documents n’ont pas besoin d’avoir les mêmes champs, ils ne sont donc pas liés au même schéma. Par exemple, vous pouvez omettre l’emplacement au cas où l’organisateur aurait besoin d’être appelé avant chaque rencontre:

Bien que vous puissiez ajouter ou omettre des champs à volonté, le type de chaque champ est important: certains sont des chaînes, d’autres des entiers, etc. De ce fait, Elasticsearch conserve un mapping de tous vos champs, de leurs types et d’autres paramètres. Ce mapping est spécifique à chaque type de chaque index. C’est pourquoi les types sont parfois appelés « types de mapping » dans la terminologie d’Elasticsearch.

2.1.2. Les types

Les types sont des conteneurs logiques pour les documents, tout comme les tables sont des conteneurs pour les lignes. Vous avez mis des documents avec différentes structures (schémas) dans différents types. Par exemple, vous pouvez avoir un type qui définit les groupes de rencontre(get-together groups) et un autre type pour les événements lors de la rencontre.

La définition des champs dans chaque type s’appelle un mapping. Par exemple, name serait mappé en tant que String, mais le champ de géolocalisation sous location serait mappé en tant que type spécial, geo_point. (Nous explorerons l’utilisation de données géospatiales à l’annexe A.) Chaque type de champ est traité différemment. Par exemple, vous recherchez un mot dans le champ name et des groupes par emplacement pour trouver ceux qui se trouvent près de chez vous.



Chaque fois que vous effectuez une recherche dans un champ qui ne se trouve pas à la racine de votre document JSON, vous devez spécifier son chemin. Par exemple, le champ de géolocalisation sous location est appelé location.geolocation.



Vous pouvez vous demander: si Elasticsearch est dépourvu de schéma, pourquoi chaque document appartient-il à un type et chaque type contient-il un mapping, qui ressemble à un schéma?

Nous disons sans schéma car les documents ne sont pas liés à un schéma spécifique. Ils ne doivent pas contenir tous les champs définis dans votre mapping et peuvent en créer de nouveaux. Comment ça marche? Premièrement, le mapping contient tous les champs de tous les documents indexés jusqu’à présent dans ce type. Mais tous les documents ne doivent pas nécessairement comporter tous les champs. De même, si un nouveau document est indexé avec un champ qui ne figure pas déjà dans le mapping, Elasticsearch ajoute automatiquement ce nouveau champ à votre mapping. Pour ajouter ce champ, il doit décider de quel type il s’agit et le devine. Par exemple, si la valeur est 7, cela suppose qu’il s’agit d’un type long.

Cette autodétection de nouveaux champs a son inconvénient, car Elasticsearch pourrait se tromper sur le type choisit. Par exemple, après l’indexation de 7, vous voudrez peut-être indexer « hello world », ce qui échouera car il s’agit d’une String et non d’un long. En production, la méthode la plus sûre consiste à définir votre mapping avant l’indexation des données. Nous parlons plus en détail de la définition du mapping au chapitre 3.

Les types de mapping divisent uniquement les documents de manière logique. Physiquement, les documents du même index sont écrits sur le disque, quel que soit le type de mapping auquel ils appartiennent.

2.1.3. Indexes

Les index sont des conteneurs pour les types de mapping. Un index Elasticsearch est un bloc de documents indépendant, un peu comme une base de données dans le monde relationnel: chaque index est stocké sur le disque dans le même ensemble de fichiers; il stocke tous les champs de tous les types de mapping et possède ses propres paramètres. Par exemple, chaque index a un paramètre appelé refresh_interval, qui définit l’intervalle auquel les nouveaux documents indexés sont rendus disponibles pour les recherches. Cette opération d’actualisation est assez coûteuse en termes de performances, et c’est pourquoi elle est effectuée occasionnellement – par défaut, toutes les secondes – au lieu de l’être après chaque document indexé. Si vous avez entendu dire qu’Elasticsearch était quasiment en temps réel, ce processus d’actualisation est ce à quoi cela fait référence.



Tout comme vous pouvez effectuer une recherche sur plusieurs types, vous pouvez effectuer une recherche sur plusieurs index. Cela vous donne une flexibilité dans la façon dont vous pouvez organiser les documents. Par exemple, vous pouvez placer vos événements de rencontre(get-together event) et les posts de blog à leur sujet dans différents index ou dans différents types du même index. Certains moyens sont plus efficaces que d’autres, selon votre cas d’utilisation. Nous expliquons plus en détail comment organiser vos données pour une indexation efficace au chapitre 3.



Un exemple de paramètres spécifiques à l’index est le nombre de fragments. Vous avez vu au chapitre 1 qu’un index peut être composé d’un ou de plusieurs paquets appelés fragments. C’est bon pour l’évolutivité: vous pouvez exécuter Elasticsearch sur plusieurs serveurs et avoir des fragments du même index en direct sur chacun d’entre eux. Ensuite, nous examinerons de plus près le fonctionnement du sharding dans Elasticsearch.

2.2. COMPRENDRE LA DISPOSITION PHYSIQUE: LES NOEUDS ET LES FRAGMENTS

Comprendre comment les données sont physiquement structurées revient à comprendre comment évolue Elasticsearch. Bien que le chapitre 9 soit entièrement consacré à la scalabilité, je vous expliquerai dans cette section le fonctionnement de la scalabilité en examinant la manière dont plusieurs nœuds fonctionnent ensemble dans un cluster, la façon dont les données sont divisées et répliquées, et enfin comment l’indexation et la recherche fonctionnent avec plusieurs fragments et répliques.

Pour comprendre la situation dans son ensemble, examinons ce qui se produit lors de la création d’un index Elasticsearch. Par défaut, chaque index est composé de cinq fragments primaires, chacun avec une réplique, pour un total de dix fragments, comme illustré à la figure 2.3.

Comme vous le verrez ci-après, les réplicas garantissent la fiabilité et la performance des recherches. Techniquement, un fragment est un répertoire de fichiers dans lequel Lucene stocke les données de votre index. Un fragment est également la plus petite unité qu’Elasticsearch déplace d’un noeud à l’autre.

2.2.1. Création d’un cluster composé d’un ou plusieurs nœuds

Un nœud est une instance de Elasticsearch. Lorsque vous démarrez Elasticsearch sur votre serveur, vous avez un nœud. Si vous démarrez Elasticsearch sur un autre serveur, il s’agit d’un autre noeud. Vous pouvez même avoir plusieurs nœuds sur le même serveur en lançant plusieurs processus Elasticsearch.

Plusieurs nœuds peuvent rejoindre le même cluster. Comme nous le verrons plus loin dans ce chapitre, le démarrage de nœuds avec le même nom de cluster et les autres paramètres par défaut suffit pour créer un cluster. Avec un cluster de plusieurs nœuds, les mêmes données peuvent être réparties sur plusieurs serveurs. Cela améliore les performances, car Elasticsearch dispose d’avantage de ressources. Cela améliore également la fiabilité: si vous avez au moins une réplique par fragment, n’importe quel nœud peut disparaître et Elasticsearch vous servira quand même toutes les données. Pour une application utilisant Elasticsearch, le fait d’avoir un ou plusieurs nœuds dans un cluster est transparent. Par défaut, vous pouvez vous connecter à n’importe quel nœud du cluster et utiliser toutes les données comme si vous n’aviez qu’un seul nœud.

Bien que la mise en place de cluster soit bon pour les performances et la disponibilité, il présente toutefois des inconvénients: vous devez vous assurer que les nœuds peuvent communiquer entre eux assez rapidement et que vous ne disposerez pas d’un cerveau divisé (deux parties du cluster qui ne peuvent ni communiquer ni réfléchir ensemble, chaque composant pensant que l’autre a été abandonné). Pour résoudre ces problèmes, le chapitre 9 traite de l’extension (scaling out).

Que se passe-t-il lorsque vous indexez un document?
Par défaut, lorsque vous indexez un document, celui-ci est d’abord envoyé à l’un des fragments principaux, choisi en fonction du hachage de l’ID du document. Ce fragment primaire peut être situé sur un nœud différent, comme sur le nœud 2 de la figure 2.4, mais cela est transparent pour l’application.

Ensuite, le document est envoyé pour être indexé dans toutes les répliques de ce fragment principal (voir le côté gauche de la figure 2.4). Cela permet aux réplicas de rester synchronisés avec les données des fragments primaires. Le fait d’être synchronisé permet aux répliques d’effectuer des recherches et d’être automatiquement promus en fragments principaux au cas où le principal d’origine ne serait plus disponible.

Que se passe-t-il lorsque vous recherchez un index?
Lorsque vous recherchez un index, Elasticsearch doit rechercher cet index dans un ensemble complet de fragments (voir à droite de la figure 2.4). Ces fragments peuvent être primaires ou des répliques, car ils contiennent généralement les mêmes documents. Elasticsearch répartit la charge de recherche entre les fragments primaires et des répliques de l’index que vous recherchez, ce qui rend les répliques utiles à la fois pour les performances de recherche et à la tolérance aux bugs.

Nous examinerons ensuite les détails de ce que sont les fragments primaires et des répliques ensuite comment ils sont alloués dans un cluster Elasticsearch.

2.2.2. Comprendre les fragments primaires et de répliques

Commençons par la plus petite unité traitée par Elasticsearch, un fragment. Un fragment est un index Lucene: un répertoire de fichiers contenant un index inversé. Un index inversé est une structure qui permet à Elasticsearch de vous indiquer quel document contient un terme (un mot) sans avoir à consulter tous les documents.



Elasticsearch index vs. Lucene index

Le mot «index» est utilisé fréquemment lorsqu’on parle d’Elasticsearch.

Un index Elasticsearch est divisé en morceaux: fragments. Un fragment est un index Lucene. Par conséquent, un index Elasticsearch est composé de plusieurs index Lucene. Cela a du sens, car Elasticsearch utilise Apache Lucene comme bibliothèque principale pour indexer vos données et les rechercher.

Tout au long de ce livre, chaque fois que vous voyez le mot «index» utilisé tout seul, il fait référence à un index Elasticsearch. Si je vais plus loin dans le détail, j’utiliserai plus précisément le terme «index Lucene».



Dans la figure 2.5, vous pouvez voir le type d’informations que le premier fragment primaire de votre index get-together peut contenir. Le fragment get-together0, comme nous l’appellerons désormais, est un index Lucene, un index inversé. Par défaut, il stocke le contenu du document original ainsi que des informations supplémentaires, telles que le dictionnaire des termes et leurs fréquences, ce qui facilitent la recherche.

Le dictionnaire de termes associe chaque termes aux identifiants des documents contenant ce dernier(voir figure 2.5). Lors de la recherche, Elasticsearch n’a pas à parcourir tous les documents pour le retrouver. Il utilise ce dictionnaire pour identifier rapidement tous les documents correspondants.

La fréquence des termes donne à Elasticsearch un accès rapide au nombre d’apparences d’un terme dans un document. Ceci est important pour calculer le score de pertinence des résultats. Par exemple, si vous recherchez «denver», les documents contenant «denver» plusieurs fois sont généralement plus pertinents. Elasticsearch leur donne un score plus élevé, et ils apparaissent plus haut dans la liste des résultats. Par défaut, l’algorithme de classement est TF-IDF, comme expliqué au chapitre 1, section 1.1.2, mais vous disposez de beaucoup plus d’options. Nous aborderons la pertinence de la recherche en détail au chapitre 6.

Un fragment peut être un fragment principal ou un fragment de réplique, communément appelés replicas: des copies du fragment principal. Une réplique est utilisée pour la recherche ou devient une nouvelle partition principale si la partition primaire d’origine est perdue.

Un index Elasticsearch est composé d’un ou plusieurs fragments primaires et de zéro ou plusieurs fragments de répliques. Dans la figure 2.6, vous pouvez voir que l’index get-together d’Elasticsearch est composé de six fragments au total: deux fragments primaires (les cases les plus sombres) et deux répliques (replicas) pour chaque fragments (les cases plus claires), soit un total de quatre répliques.



Les répliques peuvent être ajoutées ou supprimées au moment de l’exécution.

Vous pouvez modifier le nombre de réplicas par fragment à tout moment, car les réplicas peuvent toujours être créés ou supprimés. Ceci ne s’applique pas au nombre de fragments primaires par lequel un index est divisé; vous devez décider du nombre de fragments avant de créer l’index.

N’oubliez pas que trop peu de fragments limitent votre capacité d’évolutivité, mais trop de fragments affectent les performances. Le réglage par défaut de cinq est généralement un bon début. Vous en apprendrez plus au chapitre 9, consacré à la scalabilité. Nous expliquerons également comment ajouter / supprimer dynamiquement des fragments de répliques.



Tous les fragments et les répliques que vous avez vus jusqu’à présent sont distribués dans les nœuds d’un cluster Elasticsearch. Nous verrons ensuite quelques détails sur la manière dont Elasticsearch distribue les fragments et les répliques dans un cluster comportant un ou plusieurs noeuds.

2.2.3. Fragments distribués dans un cluster

Le cluster Elasticsearch le plus simple comporte un nœud: une machine exécutant un processus Elasticsearch. Lorsque vous avez installé Elasticsearch au chapitre 1 et que vous l’avez démarré, vous avez créé un cluster à un nœud.

Lorsque vous ajoutez plusieurs nœuds au même cluster, les partitions existantes sont équilibrées entre tous les nœuds. Par conséquent, les requêtes d’indexation et de recherche qui fonctionnent avec ces fragments bénéficient de la puissance supplémentaire de vos nœuds ajoutés. On parle ici d’une scalabilité horizontale (en ajoutant des nœuds à un cluster). vous ajoutez plus de nœuds et les demandes sont ensuite distribuées afin qu’elles partagent le travail. L’alternative est celle verticale; vous ajoutez plus de ressources à votre nœud Elasticsearch, peut-être en y dédiant davantage de processeurs s’il s’agit d’une machine virtuelle, ou en ajoutant de la RAM à une machine physique. Bien que celle verticale améliore les performances presque à chaque fois, elle n’est pas toujours possible, ni même rentable. L’utilisation de fragments vous permet d’opter pour une scalabilité horizontale.

Supposons que vous souhaitiez améliorer la scalabilité de votre index get-together, qui comporte actuellement deux fragments principaux et aucun réplica. Comme le montre la figure 2.7, la première option consiste à scaler au niveau du nœud de façon verticale: par exemple, en ajoutant plus de RAM, plus de processeurs, des disques plus rapides, etc. La deuxième option consisterait à scaler horizontalement en rajoutant un autre nœud et en répartissant vos données entre les deux nœuds.

Nous parlerons plus en détail de performances au chapitre 10. Pour l’instant, voyons comment l’indexation et la recherche fonctionnent sur plusieurs partitions et répliques.

2.2.4. Indexation et recherche distribuées

À ce stade, vous vous demandez peut-être comment l’indexation et la recherche fonctionnent avec plusieurs fragments répartis sur plusieurs nœuds.

Prenons l’indexation, comme le montre la figure 2.8. Le nœud Elasticsearch qui reçoit votre demande d’indexation sélectionne d’abord le fragment vers lequel indexer le document. Par défaut, les documents sont répartis équitablement entre les fragments: pour chaque document, le fragment est déterminé en hachant sa chaîne(String) d’ID. Chaque fragment a une plage de hachage égale, avec des chances égales de recevoir le nouveau document. Une fois que le fragment cible est déterminé, le nœud actuel transfère le document au nœud contenant ce fragment. Par la suite, cette opération d’indexation est rejouée par toutes les répliques de cette partition. La commande d’indexation renvoie un succès une fois que tous les réplicas disponibles ont fini d’indexer le document.

Avec la recherche, le nœud qui reçoit la demande la transfère à un ensemble de fragments contenant toutes vos données. À l’aide d’une répétition alternée, Elasticsearch sélectionne un fragment disponible (qui peut être primaire ou répliqué) et lui transmet la requête de recherche. Comme le montre la figure 2.9, Elasticsearch collecte ensuite les résultats de ces fragments, les regroupe en une seule réponse et les renvoie à l’application cliente.

Par défaut, les fragments primaires et de répliques sont touchés par les recherches en alternance, en supposant que tous les nœuds de votre cluster dispose de la même vitesse de traitement (configurations matérielle et logicielle identiques). Si ce n’est pas le cas, vous pouvez organiser vos données ou configurer vos fragments pour éviter que les nœuds plus lents ne deviennent un goulot d’étranglement. Nous allons explorer ces options plus en détail au chapitre 9. Pour le moment, commençons l’indexation des documents dans le cluster Elasticsearch à un seul noeud que vous avez démarré au chapitre 1.

2.3. INDEXATION DE NOUVELLES DONNÉES

Bien que le chapitre 3 aborde les détails de l’indexation, le but est de vous donner une idée de ce dont il est question. Dans cette section, nous aborderons les processus suivants:

  • Avec CURL, vous utiliserez l’API REST pour envoyer un document JSON à indexer àElasticsearch. Vous verrez également la réponse JSON qui revient.
  • Vous verrez comment Elasticsearch crée automatiquement l’index et le type auxquels votre document appartient s’ils n’existent pas déjà.
  • Vous indexerez des documents supplémentaires à partir du code source du livre afin de disposer d’un ensemble de données prêt à être parcouru.

Vous indexerez manuellement votre premier document. Commençons par examiner comment envoyer une demande HTTP PUT à une URI. Un exemple d’URI est présenté à la figure 2.10 avec chaque partie étiquetée.

Passons en revue la façon dont vous émettez la demande.

2.3.1. Indexer un document avec CURL

Pour la plupart des extraits de ce livre, vous utiliserez les binaires de la library CURL. CURL est un outil de ligne de commande permettant de transférer des données via le protocole HTTP. Vous utiliserez la commande curl pour effectuer des requêtes HTTP, car il est devenu courant de l’utiliser avec Elasticsearch. C’est parce qu’il est facile de traduire une instruction sous cURL dans n’importe quel langage de programmation. En fait, si vous demandez de l’aide sur la liste de diffusion officielle d’Elasticsearch, il est recommandé de fournir une « récréation CURL ». Une récréation curl est une commande ou une séquence de commandes curl reproduisant le problème que vous rencontrez. Ainsi toute personne ayant installé Elasticsearch en local peut l’exécuter.



Instatllation de CURL

Si vous utilisez un système d’exploitation de type UNIX, tel que Linux ou Mac OS X, la commande curl sera probablement disponible. Si vous ne l’avez pas, vous pouvez le télécharger à partir de http://curl.haxx.se. Vous pouvez également installer Cygwin, puis sélectionner CURL.

Il est préférable d’utiliser Cygwin pour exécuter des commandes curl sous Windows, car vous pouvez copier-coller les commandes qui fonctionnent sur des systèmes de type UNIX. Si vous choisissez de vous en tenir au shell Windows, faites très attention car les guillemets simples se comportent différemment sous Windows. Dans la plupart des situations, vous devez remplacer les guillemets simples (‘) par des guillemets doubles (« ) et échapper les guillemets doubles par une barre oblique inversée (\ »). Par exemple, une commande UNIX comme celle-ci:

ressemble à ceci sur Windows:



Il existe plusieurs façons d’utiliser curl pour effectuer des requêtes HTTP. Exécutez la commande man curl pour toutes les voir. Tout au long de ce livre, nous utiliserons les conventions d’utilisation de curl suivantes:

  • La méthode, généralement GET, PUT ou POST, est l’argument du paramètre -X. Vous pouvez ajouter un espace entre le paramètre et son argument, mais nous n’en ajoutons pas. Par exemple, nous utilisons -XPUT au lieu de -X PUT. La méthode par défaut est GET et, lorsque nous l’utiliserons, nous ignorerons complètement le paramètre -X.
  • Dans l’URI, nous ometterons de spécifier le protocole;  curl utilisera http par défaut quand aucun protocole n’est spécifié.
    Nous mettons des guillemets simples autour de l’URI car il peut contenir plusieurs paramètres et vous devez les séparer avec une esperluette (&), ce qui permet d’exécuter le processus en l’arrière-plan, en vous rendant la main sur le terminal.
  • Les données que nous envoyons via HTTP sont généralement JSON et nous les entourerons de guillemets simples car le JSON lui-même contient des guillemets doubles. Si des guillemets simples sont nécessaires dans le JSON lui-même, nous fermerons d’abord les guillemets simples, puis nous les entourerons de guillemets doubles, comme indiqué dans cet exemple:

Pour des raisons de cohérence, la plupart des URL seront également entourées de guillemets simples (sauf lorsque l’utilisation de guillemets simples empêche d’échapper un caractère ou d’inclure une variable, alors des guillemets doubles seront utilisés).
Les URL que nous utiliserons pour les requêtes HTTP contiennent parfois des paramètres tels que pretty = true ou tout simplement pretty. Nous utiliserons ce dernier, et ceci que la demande soit faite avec un curl ou non. Le paramètre pretty en particulier rend la réponse JSON plus lisible que la synthaxe par défaut. En effet il en résulte une réponse qui tient sur une seule ligne.



Utiliser Elasticsearch à partir de votre navigateur via Head, kopf ou Marvel

Si vous préférez les interfaces graphiques aux lignes de commande, plusieurs outils sont disponibles.

Elasticsearch Head – Vous pouvez installer cet outil sous la forme d’un plug-in Elasticsearch, d’un serveur HTTP autonome ou d’une page Web que vous pouvez ouvrir à partir de votre système de fichiers. Vous pouvez envoyer des requêtes HTTP à partir de là, mais Head est plus un outil de surveillance très utile pour vous montrer comment les fragments sont distribués dans votre cluster. Vous pouvez trouver Elasticsearch Head à l’adresse https://github.com/mobz/elasticsearch-head.

Elasticsearch kopf— Semblable à Head en ce qu’il est utile à la fois pour le suivi et l’envoi de demandes, cet outil s’exécute en tant que page Web à partir de votre système de fichiers ou en tant que plug-in Elasticsearch. Head et kopf évoluent rapidement, toute comparaison risque donc de devenir rapidement obsolète. Vous pouvez trouver Elasticsearch kopf à l’adresse https://github.com/lmenezes/elasticsearch-kopf.

Marvel— Cet outil est une solution de surveillance pour Elasticsearch. Nous aborderons plus en détail la surveillance au chapitre 11, consacré à l’administration de votre cluster. Ensuite, nous décrirons des outils de surveillance tels que Marvel dans l’annexe D. Pour l’instant, il convient de rappeler que Marvel fournit également un moyen graphique d’envoyer des requêtes à Elasticsearch, appelées Sense, en fournissant une fonctionnalité de complétion automatique, qui est un outil d’apprentissage utile. Vous pouvez télécharger Marvel sur www.elastic.co/downloads/marvel. Notez que Marvel est un produit commercial, même s’il est gratuit pour le développement.



En supposant que vous puissiez utiliser la commande curl et que Elasticsearch soit installé avec les paramètres par défaut sur votre ordinateur local, vous pouvez indexer votre premier document de groupe get-together à l’aide de la commande suivante:

Vous devriez obtenir le résultat suivant:

La réponse contient l’index, le type et l’ID du document indexé. Dans ce cas, vous obtenez ceux que vous avez spécifiés, mais il est également possible de compter sur Elasticsearch pour générer des identifiants, comme indiqué au chapitre 3. Vous obtenez également la version du document, qui commence à 1 et est incrémentée à chaque mise à jour. Vous en apprendrez plus sur les mises à jour au chapitre 3.

Maintenant que votre premier document est indexé, voyons ce qui s’est passé avec l’index et le type contenant ce document.

2.3.2. Création d’un type d’index et de mapping

Si vous avez installé Elasticsearch et exécuté la commande curl pour indexer un document, vous vous demandez peut-être pourquoi cela a fonctionné en dépit des facteurs suivants:

  • L’index n’était pas là avant. Vous n’avez pas lancé de commande pour créer un index nommé « get-together ».
  • Le mapping n’était pas défini auparavant. Vous n’avez défini aucun type de mapping appelé groupe dans lequel définir les champs de votre document.

La commande curl fonctionne car Elasticsearch ajoute automatiquement l’index get-together pour vous et crée également un nouveau mapping pour le type groupe. Ce mapping contient une définition de votre champ sous forme de chaînes. Elasticsearch gère tout cela pour vous par défaut, ce qui vous permet de démarrer l’indexation sans configuration préalable. Vous pouvez modifier ce comportement par défaut si vous en avez besoin, comme vous le verrez au chapitre 3.

Créer un index manuellement
Vous pouvez toujours créer un index avec une requête PUT similaire à la requête utilisée pour indexer un document:

La création de l’index lui-même prend plus de temps que la création d’un document. Vous souhaiterez donc peut-être que l’index soit prêt au préalable. Si vous souhaitez définir des paramètres différents de ceux définis par défaut pour Elasticsearch, vous pouvez également créer des index à l’avance. Par exemple, vous souhaiterez peut-être un nombre spécifique de fragments. Nous allons vous montrer comment faire ces choses au chapitre 9, car vous utiliseriez généralement beaucoup d’index afin d’améliorabilité la scalabilité de votre système.

Mise en place du mapping

Comme nous l’avons mentionné, le mapping est automatiquement créé avec votre nouveau document et Elasticsearch détecte automatiquement votre name et les champs organizer comme des Strings. Si vous ajoutez un nouveau document avec encore un nouveau champ, Elasticsearch en devine également le type et ajoute le nouveau champ au mapping.

Pour afficher le mapping actuel, envoyez un HTTP GET à l’endpoint _mapping de l’index. Cela vous montrera le mapping de tous les types de cet index, mais vous pouvez obtenir un mapping spécifique en spécifiant le nom du type lors de l’appel à l’endpoint _mapping de l’index:

La réponse contient les données pertinentes suivantes:

  • Nom d’index – get-together
  • Nom du type – group
  • Liste de propriétés: name et organizer
  • Options de propriété – L’option type est une String pour les deux propriétés

Le chapitre 3 traite davantage des index, des mapping et des types de mapping. Pour l’instant, définissons un mapping, puis indexons certains documents en exécutant un script à partir des exemples de code fournis dans ce livre.

2.3.3. Indexation des documents à partir des exemples de code

Avant de lancer une recherche dans les documents indexés, passons à l’indexation en exécutant le script populate.sh à partir des exemples de code. Cela vous donnera quelques exemples de données supplémentaires afin de pouvoir effectuer des recherches ultérieurement.



Télécharger les exemples de code

Pour télécharger le code source, rendez-vous à l’adresse https://github.com/dakrone/elasticsearch-in-action, puis suivez les instructions à partir de cet emplacement. Le moyen le plus simple de les obtenir est de cloner le référentiel:

Si vous utilisez Windows, il est préférable d’installer Cygwin d’abord à partir de https://cygwin.com. Pendant l’installation, ajoutez git et curl à la liste des paquets à installer. Ensuite, vous pourrez utiliser git pour télécharger les exemples de code et bash pour les exécuter.



Le script supprime d’abord l’index get-together que vous avez créé. Ensuite, il le recrée et crée le mapping défini dans mapping.json. Le fichier de mapping spécifie des options autres que celles que vous avez vues jusqu’à présent. Nous les explorerons dans le reste du livre, principalement au chapitre 3. Enfin, le script indexe les documents sous deux types: groupe et événement. Il existe une relation parent-enfant entre ces types (événements appartenant à des groupes), que nous explorons au chapitre 8. Pour l’instant, ignorez cette relation.

L’exécution du script populate.sh doit ressembler à la liste suivante:

Après avoir exécuté le script, vous aurez une poignée de groupes qui se rencontreront et les événements planifiés pour ces derniers. Voyons comment effectuer des recherches dans ces documents.

2.4. RECHERCHE ET RÉCUPÉRATION DE DONNÉES

Comme vous pouvez l’imaginer, il existe de nombreuses options pour la recherche. Après tout, c’est le coeur de metier d’Elasticsearch.



Nous examinerons les méthodes de recherche les plus courantes au chapitre 4. Vous en apprendrez plus sur l’obtention de résultats pertinents au chapitre 6 et enfin sur les performances de recherche au chapitre 10.



Pour examiner de plus près les éléments qui constituent une recherche typique, recherchez les groupes contenant le mot «elasticsearch» mais demandez uniquement les champs name et location du document le plus pertinent. La liste suivante montre la demande et la réponse GET.

Normalement, une requête s’exécute sur un champ spécifique, tel que q = name: elasticsearch, mais dans ce cas, nous n’avons spécifié aucun champ car nous voulions effectuer une recherche dans tous les champs. En fait, Elasticsearch utilise par défaut un champ spécial nommé _all, dans lequel le contenu de tous les champs est indexé. Nous nous intéresserons davantage au champ _all du chapitre 3, mais pour le moment, il est bon de savoir qu’une telle requête sans nom de champ explicite y figure.

Nous examinerons de nombreux autres aspects de recherches dans le chapitre 4. Ici nous nous intéresserons de plus près à trois éléments importants d’une recherche:

  • Où chercher
  • Contenu de la réponse
  • Quoi et comment chercher

2.4.1. Où chercher

Vous pouvez indiquer à Elasticsearch de rechercher un type spécifique d’index, comme dans la figure  2.2, mais vous pouvez également rechercher plusieurs types dans le même index, dans plusieurs index ou dans tous les index.

Pour effectuer une recherche dans plusieurs types, utilisez une liste séparée par des virgules. Par exemple, pour effectuer une recherche dans les types groupe et événement, exécutez une commande comme celle-ci:

Vous pouvez également rechercher tous les types d’index en envoyant votre requêtte à l’endpoint _search sur l’URL de l’index:

Pareil que pour les types, pour rechercher dans plusieurs index, séparez-les par une virgule:

Cette demande particulière échouera à moins que vous n’ayez créé un autre index à l’avance. Pour ignorer de tels problèmes, vous pouvez ajouter le flag ignore_unavailable de la même manière que vous ajoutez le flag pretty. Pour rechercher dans tous les index, omettez le nom de l’index:



Si vous devez rechercher dans tous les index, vous pouvez également utiliser un terme réservé appelé _all comme nom d’index. Cela s’avère pratique lorsque vous devez rechercher dans un type unique parmi tous les index, comme dans cet exemple: http: // localhost: 9200 / _all / event / _search.



Cette flexibilité quant à l’emplacement de la recherche vous permet d’organiser les données dans plusieurs index et types, en fonction de ce qui convient à votre cas d’utilisation. Par exemple, les événements de logs sont souvent organisés en index temporels, tels que «logs-2013-06-03», «logs-2013-06-04», etc. Une telle conception implique que l’indice d’aujourd’hui est soit plus pertinent: tous les nouveaux événements sont enregistrés ici et la plupart des recherches se font dans des données récentes. Un index pareil ne contient qu’une fraction de toutes vos données, ce qui le rend plus facile à gérer et plus rapide. Et vous pouvez toujours rechercher dans des données plus anciennes ou dans toutes les données si vous en avez besoin. Vous en apprendrez plus sur ces modèles de conception dans la deuxième partie, lorsque vous decouvrirez la scalabilité, les performances et l’administration.

2.4.2. Contenu de la réponse

Outre les documents correspondant à vos critères de recherche, la réponse d’une recherche contient des informations utiles pour vérifier les performances de votre recherche et la pertinence des résultats.

Vous avez peut-être des questions sur la figure 2.2 concernant le contenu de la réponse d’Elasticsearch. De quoi parle le score? Que se passe-t-il si tous les fragments ne sont pas disponibles? Examinons chaque partie de la réponse figurant dans la figure suivante.

Comme vous pouvez le constater, la réponse JSON d’Elasticsearch comprend des informations sur l’heure, les fragments, les statistiques et les documents demandés. Nous examinerons chacune d’elles à tour de rôle.

Les premiers éléments d’une réponse ressemblent à ceci:

Le champ « took » vous indique le temps nécessaire à Elasticsearch pour traiter votre demande. Le temps est en millisecondes. Le champ timed_out indique si votre recherche a expiré. Par défaut, les recherches n’expirent jamais, mais vous pouvez spécifier une limite via le paramètre timeout. Par exemple, la recherche suivante expire après trois secondes:

Si une recherche expire, la valeur du timed_out est true et vous obtenez uniquement les résultats qui ont été rassemblés jusqu’à ce que la recherche ait expiré.

Fragments
Ensuite on a les informations sur les fragments impliqués dans la recherche:

Cela peut vous sembler naturel, car vous avez effectué une recherche dans un index, qui dans ce cas comporte deux fragments. Tous les fragments ont répondu. Les 2 fragments ont répondu avec succès. D’où le nombre d’échecs à 0.

Vous pourriez vous demander ce qui se passe lorsqu’un nœud tombe en panne et qu’un fragment ne peut répondre à une requête de recherche. Regardez la figure 2.11, qui montre un cluster de trois nœuds, chacun avec un seul fragment et pas de réplicas. Si un nœud tombe en panne, il manque des données. Dans ce cas, Elasticsearch vous fournit les résultats des partitions qui sont actives et indique le nombre de partitions non disponibles pour la recherche en question sur le champ failed.

Le dernier élément de la réponse s’appelle hits et est assez long car il contient un tableau des documents correspondants. Mais avant ce tableau, il contient quelques statistiques:

Au total, vous voyez le nombre total de documents correspondants et dans max_score, le score maximum de ces derniers.



Définition

Le score d’un document renvoyé par une recherche est la mesure de la pertinence de ce document pour les critères de recherche donnés. Comme indiqué au chapitre 1, le score est calculé par défaut avec l’algorithme TF-IDF (fréquence des termes – fréquence inverse du document). La fréquence des termes signifie que pour chaque terme (mot) que vous recherchez, le score du document est augmenté s’il contient plus d’occurrences de ce terme. Une fréquence de document inverse signifie que le score augmente davantage si le terme est rare dans tous les documents, car il est considéré comme plus pertinent. Si le terme apparaît souvent dans d’autres documents, il s’agit probablement d’un terme commun, et est donc moins pertinent. Nous allons vous montrer comment rendre vos recherches plus pertinentes au chapitre 6.



Le nombre total de documents peut ne pas correspondre au nombre de documents que vous voyez dans la réponse. Par défaut, Elasticsearch limite le nombre de résultats à 10; par conséquent, si vous pouvez en gerer plus de 10, examinez la valeur de total pour connaître le nombre précis de documents correspondant à vos critères de recherche. Comme vous l’avez vu précédemment, utilisez le paramètre size pour modifier le nombre de résultats renvoyés.

Documents résultants

Le tableau des hits est généralement l’information la plus intéressante dans une réponse:

Chaque document correspondant est affiché avec l’index et le type auquel il appartient, son ID et son score. Les valeurs des champs que vous avez spécifiés dans votre requête de recherche sont également affichées. Dans la figure 2.2, vous avez utilisé le field = name, location. Si vous ne spécifiez pas les champs de votre choix, le champ _source est affiché. Comme _all, _source est un champ spécial dans lequel Elasticsearch stocke par défaut le document JSON d’origine. Vous pouvez configurer ce qui est stocké dans ce champ, et nous l’explorerons au chapitre 3.



Vous pouvez également limiter les champs du document d’origine (_source) qui seront affichés en utilisant le filtre adéquat, comme expliqué ici: www.elastic.co/guide/fr/elasticsearch/reference/master/search-request-source-filtering.html . Vous placerez ces options dans la charge JSON de votre recherche, comme expliquée dans la section suivante.



2.4.3. Comment chercher

Jusqu’ici, vous avez effectué une recherche à travers ce que vous appelez une requête REST (URI). En effet ici toutes vos options de recherche vont dans l’URI. C’est bien pour les recherches simples que vous exécutez en ligne de commande, mais il est plus prudent de considérer ce type de requêtes comme des raccourcis.

Normalement, vous devriez placer votre query dans la partie données de votre requête. Elasticsearch vous permet de spécifier tous les critères de recherche au format JSON. En effet à mesure que les recherches deviennent plus complexes, le format JSON est beaucoup plus facile à lire et à écrire et offre beaucoup plus de fonctionnalités.

Pour envoyer une requête JSON pour récupérer tous les groupes concernant Elasticsearch, vous pouvez procéder comme suit:

En clair, cela se traduit par «exécuter une requête de type query_string, où la chaîne est elasticsearch». Cela peut sembler trop compliqué de taper elasticsearch, mais JSON fournit beaucoup plus d’options qu’une requête URI. Comme vous le verrez au chapitre 4, l’utilisation d’une requête JSON est utile lorsque vous commencez à combiner différents types de requête: il serait plus difficile de compresser toutes ces options dans une URI. Regardons de plus près chaque champs.

Définition des options de chaîne de requête
Au dernier niveau de la requête JSON, vous avez « query« : « elasticsearch« , et vous pouvez penser que la partie « query » est redondante car vous savez déjà que c’est une requête. Mais une query_string fournit plus d’options que la chaîne elle-même.

Par exemple, si vous recherchez «elasticsearch san francisco», Elasticsearch recherche par défaut dans le champ _all. Si vous souhaitez plutôt rechercher le nom du groupe, vous devez spécifier:

Par défaut, Elasticsearch renvoie également les documents correspondant à l’un des mots spécifiés (l’opérateur par défaut est OU). Si vous voulez faire correspondre tous les mots, vous devez spécifier

Par défaut, Elasticsearch renvoie également les documents correspondant à l’un des mots spécifiés (l’opérateur par défaut est OU). Si vous voulez faire correspondre tous les mots, vous devez spécifier

La requête finale ressemble à ceci:

Un autre moyen d’obtenir les mêmes résultats consiste à spécifier le champ et l’opérateur dans la chaîne de requête elle-même:

La chaîne de requête est un outil puissant pour spécifier vos critères de recherche. Elasticsearch analyse la chaîne pour comprendre les termes que vous recherchez et vos autres options, telles que les champs et les opérateurs, puis exécute la requête. Cette fonctionnalité est héritée de Lucene.

Choisir le bon type de requête
Si le type de requête query_string semble intimidant, la bonne nouvelle est qu’il existe de nombreux autres types de requêtes, dont la plupart sont abordées au chapitre 4. Par exemple, si vous recherchez uniquement le terme «elasticsearch» dans le champ name, la requête de terme serait plus rapide et plus simple:

Utiliser des filtres
Jusqu’à présent, toutes les recherches que vous avez vues sont des requêtes. Les requêtes vous donnent des résultats où chaque résultat a un score. Si le score ne vous intéresse pas, vous pouvez exécuter une requête filtrée. Nous parlerons davantage de la requête filtrée dans le chapitre 4, mais l’information clé est que les filtres ne font que vérifier si un résultat correspond à la recherche ou non. En conséquence, ils sont plus rapides et plus faciles à mettre en cache que leurs homologues « query ». Par exemple, la requête suivante recherche le terme «elasticsearch» dans le champ de nom des documents de groupe:

Les résultats sont les mêmes que ceux que vous obtenez avec la query de terme équivalent, mais les résultats de filtre ne sont pas triés par score (car le score est 1.0 pour tous les résultats).

Appliquer des agrégations
Outre les requêtes et les filtres, vous pouvez effectuer toutes sortes de statistiques via des agrégations. Nous examinons les agrégations au chapitre 7, mais examinons un exemple simple ici.

Supposons qu’un utilisateur visite votre site Web de rencontre et souhaite explorer les types de groupes disponibles. Vous voudrez peut-être montrer qui sont les organisateurs de groupe. Par exemple, si «Lee» apparaît dans les résultats en tant qu’organisateur de sept réunions, un utilisateur connaissant Lee peut cliquer sur son nom pour filtrer uniquement ces sept réunions.

Pour renvoyer les personnes qui sont des organisateurs de groupe, vous pouvez utiliser une agrégation de termes. Cela affiche les compteurs pour chaque terme qui apparaît dans le champ que vous avez spécifié, en l’occurrence, l’organisateur. L’agrégation pourrait ressembler à ceci:

En clair, cette demande signifie « donnez-moi une agrégation nommée organizers, qui est de type terms et examine le champ organizers« . Les résultats suivants s’affichent au bas de la réponse:

Les résultats vous montrent que sur les six termes au total, “lee” apparaît deux fois, “andy” une fois, etc. Nous avons deux groupes organisés par Lee. Vous pouvez ensuite rechercher les groupes dont Lee est l’organisateur pour affiner vos résultats.

Les agrégations sont utiles lorsque vous ne pouvez pas rechercher ce dont vous avez besoin car vous ne savez pas ce que c’est. Quels types de groupes sont disponibles? Y a-t-il des événements organisés près de chez moi? Vous pouvez utiliser des agrégations pour explorer les données disponibles et consulter des statistiques en temps réel.

À d’autres moments, vous avez le scénario opposé. Vous savez exactement ce dont vous avez besoin et vous ne voulez pas du tout lancer une recherche à l’aveugle. C’est à ce moment-là qu’il est utile de récupérer un document par son ID.

2.4.4. Obtenir des documents par ID

Pour récupérer un document spécifique, vous devez connaître l’index, le type auquel il appartient et son identifiant. Vous envoyez ensuite une requête HTTP GET à l’URI de ce document:

La réponse contient l’index, le type et l’ID que vous avez spécifiés. Si le document existe, vous verrez que le champ trouvé est vrai, en plus de sa version et de sa source. Si le document n’existe pas, la valeur trouvée est false:

Comme vous vous en doutez, obtenir des documents par ID est beaucoup plus rapide et moins coûteux en ressources que la recherche. Cela se fait également en temps réel: dès qu’une opération d’indexation est terminée, le nouveau document peut être récupéré via cette API GET. En revanche, les recherches se font presque en temps réel car elles doivent attendre une actualisation, ce qui se produit par défaut toutes les secondes.

Maintenant que vous avez compris comment traiter toutes les requêtes d’API de base, voyons comment modifier certaines options de configuration de base.

2.5. CONFIGURER ELASTICSEARCH

Un des points forts d’Elasticsearch est qu’il dispose de paramètres par défaut corrects pour la plupart des développeurs, ce qui facilite la mise en route. Comme vous l’avez vu dans la section précédente, vous pouvez indexer et faire des recherches sur votre propre serveur de test sans apporter de modification à la configuration. Elasticsearch crée automatiquement un index et détecte le type de nouveaux champs dans vos documents.

Elasticsearch évolue facilement et efficacement, ce qui est une autre caractéristique importante lorsque vous traitez de grandes quantités de données ou de requêtes. Dans la dernière section de ce chapitre, vous allez lancer une deuxième instance Elasticsearch, en plus de celle que vous avez déjà lancée au chapitre 1, et les laisser former un cluster. Ainsi, vous verrez comment Elasticsearch évolue et distribue vos données dans le cluster.

Bien que l’amélioration de la scalabilité puisse s’effectuer sans modification de la configuration, modifiez quelques options dans la section ci-dessous pour éviter les surprises plus tard, lorsque vous ajouterez un deuxième nœud. Vous apporterez les modifications suivantes dans trois fichiers de configuration différents:

  • Spécifiez un nom de cluster dans elasticsearch.yml: il s’agit du fichier de configuration principal vers lequel les options spécifiques à Elasticsearch vont.
  • Modifier les options de logging dans le fichier logging.yml: le fichier de configuration des logs concerne les options de logging de log4j, la bibliothèque utilisée par Elasticsearch pour les logs.
  • Ajuster les paramètres de mémoire dans les variables d’environnement ou dans elasticsearch.in.sh: ce fichier permet de configurer la machine virtuelle Java (JVM) qui alimente Elasticsearch.

Il existe de nombreuses autres options, et nous en indiquerons quelques-unes au fur et à mesure, mais celles qui sont répertoriées ici sont les plus utilisées. Passons en revue chacune de ces modifications.

2.5.1. Spécification d’un nom de cluster dans elasticsearch.yml

Le fichier de configuration principal d’Elasticsearch se trouve dans le répertoire config / de l’archive tar.gz ou ZIP décompressée.



Astuce

Le fichier est dans /etc/elasticsearch/ si vous l’avez installé à partir du package RPM ou DEB.



À l’instar de l’API REST, la configuration peut être en JSON ou en YAML. Contrairement à l’API REST, le format le plus populaire est YAML. C’est plus facile à lire et à utiliser. Du coup tous les exemples de configuration de ce livre sont basés sur elasticsearch.yml.

Par défaut, les nouveaux nœuds découvrent les clusters existants via la multidiffusion, en envoyant un ping à tous les hôtes écoutant sur une adresse de multidiffusion bien spécifique. Si un cluster est découvert, le nouveau nœud le rejoint s’il porte le même nom de cluster. Vous allez personnaliser le nom du cluster pour empêcher les instances de la configuration par défaut de rejoindre votre cluster. Pour changer le nom du cluster, décommentez et changez la ligne cluster.name de votre elasticsearch.yml:

Après avoir mis à jour le fichier, arrêtez Elasticsearch en appuyant sur Control-C, puis relancez-le à l’aide de la commande suivante:



Attention
Si vous avez indexé certaines données, vous remarquerez peut-être qu’après le redémarrage d’Elasticsearch avec un nouveau nom de cluster, il n’ya plus de données. C’est parce que le répertoire dans lequel les données sont stockées contient le nom du cluster. Vous pouvez donc revenir aux données indexées en modifiant le nom du cluster et en le redémarrant. Pour l’instant, vous pouvez réexécuter populate.sh à partir des exemples de code pour réintégrer les exemples de données.



2.5.2. Spécification de la journalisation détaillée via logging.yml

En cas de problème, les logs d’application sont le premier endroit où rechercher des indices. Ils sont également utiles lorsque vous voulez simplement voir ce qui se passe. Si vous devez consulter les logs Elasticsearch, l’emplacement par défaut est le répertoire logs / situé sous le chemin où vous avez décompressé l’archive zip / tar.gz.



Astuce
Si vous l’avez installé à partir du package RPM ou DEB, le chemin par défaut est / var / log / elasticsearch /.



Les entrées de logs Elasticsearch sont organisées en trois types de fichiers:

  • Logs principal (nom-cluster.log) – Vous trouverez ici des informations générales sur ce qui se passe pendant l’exécution d’Elasticsearch. Par exemple, si une requête a échoué ou si un nouveau nœud a rejoint le cluster.
  • Logs de recherche lente (nom_groupe_index_search_slowlog.log) – C’est ici que se loge Elasticsearch lorsqu’une requête est trop lente. Par défaut, si une requête prend plus d’une demi-seconde, elle enregistre une entrée ici.
  • Logs d’indexs lents (nom_groupe_index_indexing_slowlog.log): il est similaire au journal de recherche lente, mais il écrit par défaut une entrée si une opération d’indexation prend plus d’une demi-seconde.

Pour modifier les options de journalisation, modifiez le fichier logging.yml, qui se trouve au même endroit que elasticsearch.yml. Elasticsearch utilise log4j (http://logging.apache.org/log4j/) et les options de configuration de logging.yml sont spécifiques à cet utilitaire de journalisation.

Comme pour les autres paramètres, les valeurs par défaut sont judicieuses, mais si, par exemple, vous avez besoin d’une journalisation plus détaillée, une première étape consiste à modifier le rootLogger, qui influence toute la journalisation. Nous allons laisser les valeurs par défaut pour le moment, mais si vous voulez que absolument tout soit consigné dans le fichier de log, modifiez la première ligne de logging.yml en ceci:

Par défaut, le niveau de journalisation est INFO, qui écrit tous les événements dont le niveau de gravité est INFO ou supérieur.

2.5.3. Réglage des paramètres de la machine virtuelle Java

En tant qu’application Java, Elasticsearch s’exécute dans une machine virtuelle Java qui, à l’instar d’une machine physique, possède sa propre mémoire. La machine virtuelle Java est livrée avec sa propre configuration, la plus importante étant la quantité de mémoire que vous lui permettez d’utiliser. Choisir le bon paramètre de mémoire est important pour la performance et la stabilité d’Elasticsearch.

La majeure partie de la mémoire utilisée par Elasticsearch est appelée heap. Le paramètre par défaut permet à Elasticsearch d’allouer initialement 256 Mo de RAM à son segment de mémoire et de l’étendre jusqu’à 1 Go. Si vos recherches ou vos opérations d’indexation nécessitent plus de 1 Go de RAM, ces opérations échoueront et vous verrez des erreurs d’insuffisance de mémoire dans vos logs. Inversement, si vous exécutez Elasticsearch sur une machine ne disposant que de 256 Mo de RAM, les paramètres par défaut risquent d’allouer trop de mémoire.

Pour modifier les valeurs par défaut, vous pouvez utiliser la variable d’environnement ES_HEAP_SIZE. Vous pouvez le définir dans la ligne de commande avant de lancer Elasticsearch.

Sur les systèmes de type UNIX, utilisez la commande export:

Sous Windows, utilisez la commande SET:

Un moyen plus permanent de définir la taille du tas (La Heap) consiste à modifier le fichier bin/elasticsearch.in.sh (et elasticsearch.bat sous Windows). Ajoutez ES_HEAP_SIZE = 500m au début du fichier, après #! / Bin / sh.



Astuce

Si vous avez installé Elasticsearch via le package DEB, modifiez ces variables dans /etc/default/elasticsearch. Si vous avez installé à partir du package RPM, les mêmes paramètres peuvent être configurés dans /etc/sysconfig/elasticsearch.



Pour la portée de ce livre, les valeurs par défaut devraient suffir. Si vous exécutez des tests plus approfondis, vous devrez peut-être allouer plus de mémoire. Si vous utilisez une machine disposant de moins de 1 Go de RAM, il convient également de réduire ces valeurs à 200 m environ.



Combien de mémoire allouer en production
Commencez avec la moitié de votre RAM totale (ES_HEAP_SIZE) si vous exécutez uniquement Elasticsearch sur ce serveur. Essayez avec moins si d’autres applications ont besoin de beaucoup de mémoire. L’autre moitié est utilisée par le système d’exploitation pour les caches, qui permettent un accès plus rapide à vos données stockées. Au-delà de cette règle empirique, vous devrez exécuter certains tests tout en contrôlant votre cluster pour déterminer la quantité de mémoire nécessaire à Elasticsearch. Je parlerai davantage de réglage et de surveillance des performances dans la deuxième partie du livre.



Maintenant que vous avez les mains dans le cambouis avec les options de configuration Elasticsearch et que vous avez indexé et effectué des recherches, vous aurez bientôt un avant-goût de la partie «élastique» d’Elasticsearch: la façon dont il évolue. (J’aborderai ce sujet en détail au chapitre 9.) Vous pouvez parcourir tous les chapitres avec un seul nœud, mais pour obtenir une vue d’ensemble du fonctionnement de la scalabilité (scaling), vous allez ajouter plus de nœuds au même cluster.

2.6 AJOUTER DES NŒUDS AU CLUSTER

Au chapitre 1, vous avez décompressé l’archive tar.gz ou ZIP et démarré votre première instance Elasticsearch. Cela a créé votre cluster à un nœud. Avant d’ajouter un deuxième nœud, vous devez vérifier l’état du cluster pour voir comment les données sont actuellement allouées. Vous pouvez le faire avec un outil graphique tel que Elasticsearch kopf ou Elasticsearch Head, que nous avons mentionné précédemment (voir section 2.3.1) lors de l’indexation d’un document. La figure 2.12 montre le cluster en kopf.

Si aucun de ces plugins n’est installé, vous pouvez toujours obtenir la plupart de ces informations à partir de l’API Cat Shards:



Astuce

La plupart des API Elasticsearch renvoient du JSON, mais les API Cat constituent une exception à cette règle et l’API Cat Shards en fait partie. Il en existe beaucoup d’autres et il est utile d’obtenir des informations sur les activités du cluster en temps réel dans un format facile à analyser à la fois par les scripts humains et les scripts shell. Nous parlerons davantage des API Cat au chapitre 11, consacré à l’administration.



De toute façon, vous devriez voir les informations suivantes:

  • Nom du cluster, tel que vous l’avez défini précédemment dans elasticsearch.yml.
  • Il n’ya qu’un seul noeud.
  • L’index get-together a deux fragments primaires, qui sont actifs. Les fragments non affectés représentent un ensemble de réplicas configurés pour cet index. Comme il n’ya qu’un seul nœud, ces réplicas ne sont pas alloués.

Les fragments de répliques non alloués donnent le statut jaune. Cela signifie que tous les fragments primaires sont là, mais pas toutes les répliques. S’il manquait des primaires, le cluster serait rouge pour signaler au moins un index incomplet. Si toutes les répliques étaient allouées, le cluster serait vert pour signaler que tout fonctionnait comme prévu, et non jaune.

2.6.1. Lancer un deuxième noeud

Depuis un autre terminal, exécutez bin/elasticsearch ou elasticsearch.bat. Cela démarre une autre instance Elasticsearch sur le même ordinateur. Vous devez normalement démarrer de nouveaux noeuds sur différentes machines pour tirer parti de la puissance de traitement supplémentaire, mais pour le moment, vous devez tout exécuter localement.

Dans le terminal ou le fichier de log du nouveau noeud, vous devriez voir une ligne qui commence:

Hammond, Jim est le nom du premier nœud. Ce qui s’est passé est que le deuxième nœud a détecté le premier via multidiffusion et a rejoint le cluster. Le premier nœud est également le maître du cluster, ce qui signifie qu’il est responsable de la conservation des informations telles que les nœuds du cluster et l’emplacement des fragments. Ces informations sont appelées état du cluster et sont répliquées sur d’autres nœuds. Si le maître tombe en panne, un autre nœud peut être choisi pour le remplacer.

Si vous regardez le statut de votre cluster à la figure 2.13, vous pouvez voir que le jeu de réplicas a été alloué au nouveau nœud, ce qui rend le cluster vert.

Si ces deux nœuds se trouvaient sur des ordinateurs distincts, vous disposeriez d’un cluster à tolérance de pannes, qui traiterait plus de recherches simultanées que jamais. Mais que se passe-t-il si vous avez besoin de plus de performances d’indexation ou de gérer encore plus de recherches simultanées? Plus de nœuds vont certainement aider.



Vous avez peut-être déjà remarqué que le premier nœud tournant sur une machine écoute sur le port 9200 de toutes les interfaces pour les requêtes HTTP. Au fur et à mesure que vous ajoutez des nœuds, il utilise les ports 9201, 9202, etc. Elasticsearch utilise les ports 9300, 9301, etc. pour la communication nœud à nœud. Ce sont des ports que vous devrez peut-être autoriser dans le pare-feu. Vous pouvez modifier les adresses d’écoute dans la section Réseau et HTTP de elasticsearch.yml.



2.6.2. Ajout de nœuds supplémentaires

Si vous exécutez à nouveau bin/elasticsearch ou elasticsearch.bat pour ajouter un troisième nœud, puis un quatrième, vous constaterez qu’ils détectent le maître via la multidiffusion et rejoignent le cluster de la même manière. De plus, comme le montre la figure 2.14, les quatre fragments de l’index get-together sont automatiquement équilibrés dans le cluster.

À ce stade, vous pourriez vous demander ce qui se passera si vous ajoutez plus de nœuds. Par défaut, rien ne se produit car vous avez au total quatre fragments qui ne peuvent pas être distribués à plus de quatre nœuds. Cela dit, si vous avez besoin de scaler d’avantage, vous avez quelques options:

  • Changer le nombre de réplicas. Les répliques peuvent être mises à jour à la volée, mais cette façon de procéder n’augmente que le nombre de recherches simultanées que votre cluster peut effectuer, car les recherches sont envoyées à des répliques du même fragment, à tour de rôle. Les performances d’indexation resteront les mêmes, car les nouvelles données doivent être traitées par tous les fragments. De plus, les recherches isolées ne seront exécutées que sur un seul ensemble de fragments. Par conséquent, l’ajout de réplicas ne vous aidera pas.
  • Créez un index avec plus de fragments. Cela implique une réindexation de vos données car le nombre de fragments primaires ne peut pas être modifié à la volée.
  • Ajouter plus d’indices. Certaines données peuvent facilement être conçues pour utiliser plus d’indices. Par exemple, si vous indexez les logs, vous pouvez placer les logs de chaque jour dans son propre index.

Nous discuterons de ces modèles de dimensionnement au chapitre 9. Pour le moment, vous pouvez fermer les trois nœuds supplémentaires pour simplifier les choses. Vous pouvez arrêter un nœud à la fois et regarder les partitions être automatiquement équilibrées lorsque vous revenez à l’état initial. Si vous les fermez tous en même temps, le premier nœud restera avec un fragment, n’ayant pas le temps de récupérer le reste des données. Dans ce cas, vous pouvez exécuter populate.sh à nouveau, ce qui réindexera toutes les données exemple.

2.7 RÉSUMÉ

Passons en revue ce que vous avez appris dans ce chapitre:

  • Elasticsearch est orienté document, évolutif et sans schéma par défaut.
  • Bien que vous puissiez former un cluster avec les paramètres par défaut, vous devez au moins en ajuster quelques-uns avant de poursuivre. Par exemple, le nom du cluster et la taille du tas(HEAP).
  • Les demandes d’indexation sont réparties entre les partitions principales et répliquées vers les répliques de ces partitions.
  • Les recherches sont effectuées à l’aide d’une approche alternée entre des ensembles complets de données, qu’il s’agisse de fragments ou de répliques. Le nœud qui a reçu la demande de recherche agrège ensuite les résultats partiels de fragments individuels et les renvoie à l’application.
  • Les applications clientes peuvent ne pas être conscientes de la nature fragmentée de chaque index ou de l’aspect du cluster. Elles ne s’intéressent qu’aux index, aux types et aux identifiants de documents. Elles utilisent l’API REST pour indexer et rechercher des documents.
  • Vous pouvez envoyer de nouveaux documents et paramètres de recherche en tant que charge JSON d’une requête HTTP et vous obtiendrez une réponse JSON contenant les résultats.

Dans le chapitre suivant, vous obtiendrez les bases nécessaires pour organiser vos données efficacement dans Elasticsearch, connaître les types de champs que vos documents peuvent comporter et vous familiariserez avec toutes les options appropriées pour l’indexation, la mise à jour et la suppression de données.