Lorsqu’on a besoin d’une recherche plein texte puissante, on se tourne gé­né­ra­le­ment vers Apache Solr. Ce projet est toujours un bon choix. Mais depuis 2010, le marché offre une al­ter­na­tive in­té­res­sante : Elas­tic­search. Comme Solr, Elas­tic­search est basé sur Apache Lucene, mais il a d’autres ca­rac­té­ris­tiques. Nous vous ex­pli­quons les fonc­tion­na­li­tés du serveur de recherche et ex­pli­quons dans notre tutoriel Elas­tic­search comment im­plé­men­ter la recherche en texte intégral à votre projet.

Qu’est-ce qu’ Elas­tic­search ?

Compte tenu de la quantité d’in­for­ma­tions dis­po­nibles sur certains sites Web, on ne peut profiter d’une bonne in­tui­ti­vité que si une recherche fonc­tion­nelle en texte intégral est mise en œuvre. Si vous ne voulez pas vous rabattre sur les offres de Google ou de Bing pour offrir à vos visiteurs une fonction de recherche, il sera né­ces­saire d’intégrer votre propre fonction de recherche. C’est ce que vous propose Elas­tic­search. Le projet open source est basé sur le logiciel libre Apache Lucene.

Elas­tic­search offre les avantages de son pré­dé­ces­seur stable et les élargi avec d’autres ca­rac­té­ris­tiques. Tout comme avec Lucene, la recherche s’opère à l’aide d’un index : mais au lieu d’examiner tous les documents pour une demande de recherche, le programme vérifie un index de documents pré­cé­dem­ment créé dans lequel tout le contenu est remanié et stocké. Ce processus prend beaucoup moins de temps qu’avec une recherche de tous les documents.

Si Lucene laisse toute liberté quant à l’endroit et la façon d’utiliser la recherche plein texte, il vous oblige toutefois à repartir de zéro. Elas­tic­search, en revanche, permet de démarrer plus ra­pi­de­ment pour une uti­li­sa­tion sur le World Wide Web. Avec Elas­tic­search, il est possible de cons­truire un serveur de recherche stable en peu de temps, qui peut aussi être fa­ci­le­ment distribué sur plusieurs machines.

Plusieurs nœuds (dif­fé­rents serveurs) se re­joig­nent pour former un cluster. Le Sharding in­ter­vient alors : Elas­tic­search décompose l’indice et distribue les dif­fé­rentes parties (shards) à plusieurs nœuds. Cela divise la charge de calcul ; pour les grands projets, la recherche en texte intégral est alors beaucoup plus stable. Pour plus de sécurité, vous pouvez également copier les shards sur plusieurs nœuds.

Ela­tic­search est basé, à l’instar de Lucene, sur le langage de pro­gram­ma­tion orienté objet Java. Le moteur affiche les résultats de recherche au format JSON et les diffuse via un service Web REST. L’API facilite gran­de­ment l’in­té­gra­tion de la fonction de recherche dans un site Web.

En outre, Elas­tic­search offre des services sup­plé­men­taires pratiques avec les beats et logstash (appelés Elastic-Stack) de Kibana que vous pouvez utiliser pour analyser la recherche plein texte. La société Elastic, qui est à l’origine du dé­ve­lop­pe­ment d’Elas­tic­search et qui a été fondée par l’inventeur du programme, propose également des services payants, comme l’hé­ber­ge­ment Cloud.

Que propose Elas­tic­search que Google & Co. n’ont pas ?

Comme toujours, Google propose ses solutions propres, et vous pouvez donc intégrer sa fonction de recherche dans votre site Web sans aucun problème. Alors pourquoi choisir une méthode plus fas­ti­dieuse et cons­truire votre propre moteur de recherche avec Elas­tic­search ? Un élément de réponse : avec Google Custom Search (GCS), vous devenez dépendant du géant des moteurs de recherche et devez autoriser (tout du moins dans la version gratuite) la publicité dans les résultats. Avec Elas­tic­search en revanche, le code est open source, et si vous mettez en place une fonction de recherche plein texte, il vous ap­par­tient. Vous n’êtes donc dépendant de personne.

Par ailleurs, vous pouvez per­son­na­li­ser to­ta­le­ment Elas­tic­search selon vos souhaits. Si, par exemple, vous gérez une pla­te­forme ou une boutique en ligne, vous pouvez con­fi­gu­rer la fonction de recherche de sorte à pouvoir également effectuer une recherche dans les profils des uti­li­sa­teurs en­re­gis­trés. GCS atteint ra­pi­de­ment ses limites dans de telles ap­pli­ca­tions.

Elas­tic­search vs Apache Solr : quelles sont les dif­fé­rences prin­ci­pales ?

Elas­tic­search et Apache Solr sont tous deux basés sur Lucene, mais ont été dé­ve­lop­pés dans des offres in­dé­pen­dantes. De nombreux uti­li­sa­teurs se demandent quel projet choisir. Même si Elas­tic­search est un peu plus jeune et n’est pas supporté par la com­mu­nauté Apache ex­pé­ri­men­tée con­trai­re­ment à Solr, il compte main­te­nant plus d’uti­li­sa­teurs. Ceci est prin­ci­pa­le­ment dû à la sim­pli­fi­ca­tion de sa mise en œuvre. De plus, Elas­tic­search est par­ti­cu­liè­re­ment populaire en raison de son trai­te­ment des données dy­na­miques : grâce à une procédure de mise en cache spéciale, Elas­tic­search permet de ne pas avoir à saisir de mo­di­fi­ca­tions dans la totalité du cache global. Il suffit sim­ple­ment de changer un petit segment. Ceci rend Elas­tic­search plus flexible.

Cependant, le choix ne se fait en fin de compte souvent qu’en fonction des dif­fé­rentes approches de l’open source. Solr s’engage plei­ne­ment dans l’Apache Software Foun­da­tion : Community over Code. Chaque con­tri­bu­tion apportée au code est prise au sérieux et la com­mu­nauté décide ensemble des ajouts et des amé­lio­ra­tions qui seront apportés au code final. Le dé­ve­lop­pe­ment d’Elas­tic­search est différent : ce projet est également open source et est proposé sous une licence Apache gratuite, mais seule l’équipe d’Elastic décide des chan­ge­ments pour le code. Face à ce com­por­te­ment de ga­te­kee­per, certains dé­ve­lop­peurs n’y adhèrent pas et préfèrent Solr.

Tutoriel Elas­tic­search

Si vous souhaitez commencer à tra­vail­ler avec Elas­tic­search, il est conseillé tout d’abord de se fa­mi­lia­ri­ser avec les termes de base. Par exemple en ce qui concerne la structure de l’in­for­ma­tion :

  • Index : une demande de recherche sur Elas­tic­search ne s’applique jamais au contenu lui-même, mais toujours à l’index. Tous les contenus de tous les documents sont stockés et déjà préparés dans ce dossier ; la recherche prend donc peu de temps. Il s’agit d’un index inversé : pour chaque terme de recherche, l’em­pla­ce­ment où le terme peut être trouvé est indiqué.
  • Document : l’output de l’index présente les documents dans lesquels les données se trouvent. Il n’est pas né­ces­saire qu’il s’agisse de textes complets (par exemple, des articles de blog). Il suffit d’avoir des fichiers purs avec des in­for­ma­tions.
  • Field : un document se compose de plusieurs champs. En plus du champ de contenu pro­pre­ment dit, un document va contenir d’autres mé­ta­don­nées. Par exemple, Elas­tic­search peut être utilisé pour re­cher­cher des mé­ta­don­nées sur l’auteur ou sur la date de création.

Par ailleurs, quand on parle de re­ma­nie­ment des données, il s’agit avant tout de tra­vail­ler sur les « tokens ». Un al­go­rithme crée en fait des termes in­di­vi­duels à partir d’un texte complet. Pour la machine, les mots n’existent pas vraiment : un texte se compose d’une longue chaîne de ca­rac­tères et une lettre a la même valeur qu’un espace. Pour qu’un texte soit formaté de manière sig­ni­fi­ca­tive, il doit d’abord être divisé en tokens. Pour ce faire, par exemple, les whi­tes­paces (c’est-à-dire les espaces et les lignes blanches) sont utilisés comme marqueurs de mots. De plus, la pré­pa­ra­tion s’ac­com­pagne également d’une nor­ma­li­sa­tion : les mots sont écrits en mi­nus­cules et les signes de ponc­tua­tion sont ignorés. Elas­tic­search a repris toutes ces méthodes d’Apache Lucene.

Note

Dans le tutoriel suivant, nous tra­vail­lons avec la version 6.3.0 de Elas­tic­search. Si vous utilisez une version dif­fé­rente, certains exemples de code ou certaines étapes du tutoriel peuvent fonc­tion­ner dif­fé­rem­ment.

Ins­tal­la­tion

Les fichiers requis pour Elas­tic­search sont dis­po­nibles gra­tui­te­ment sur le site officiel d’Elastic. Les fichiers y sont proposés sous forme de paquets ZIP ou tar.gz, et sont donc faciles à installer sur Linux et Mac via une console.

Remarque

Elastic propose Elas­tic­search dans deux packs dif­fé­rents. La version standard inclut dans sa version d’essai des fonc­tion­na­li­tés également payantes que vous pouvez utiliser pendant un certain temps. Les packs marqués OSS (Open Source Software) en revanche ne con­tien­nent que des com­po­sants libres publiés sous la licence Apache 2.0.

Pour ZIP :

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

Pour tar.gz :

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

Té­lé­char­gez d’abord le pack, puis ajoutez la somme de contrôle de la fonction de hachage (SHA512), que vous vé­ri­fie­rez également à la troisième étape. Ensuite, dé­com­pres­sez le pack et mettez-le dans le dossier approprié.

L’archive ZIP peut également être té­lé­char­gée et utilisée pour l’ins­tal­la­tion sous Windows, car le paquet contient un fichier batch que vous pouvez exécuter. Autrement, Elastic fournit main­te­nant aussi un ins­tal­la­teur MSI, mais qui se trouve encore en phase bêta. Le fichier d’ins­tal­la­tion de ce dernier comporte une interface graphique qui vous guide avec précision tout au long du processus d’ins­tal­la­tion.

Note

Elas­tic­search étant basé sur Java, ce langage de pro­gram­ma­tion doit également être installé sur votre système. Vous pouvez par con­sé­quent té­lé­char­ger le Java De­ve­lop­ment Kit (JDK) qui est gratuit sur le site Web officiel.

Lancez main­te­nant Elas­tic­search depuis la console en naviguant vers le dossier bin et en tapant « elas­tic­search » : peu importe que vous soyez sous Linux, Mac ou Windows. Ouvrez ensuite le na­vi­ga­teur de votre choix et appelez le port suivant de l’hôte local : 'http://localhost:9200/'. Si vous avez installé Elas­tic­search cor­rec­te­ment et si Java est également configuré cor­rec­te­ment, vous devriez main­te­nant pouvoir accéder à la recherche plein texte.

Avec Elas­tic­search, vous com­mu­ni­quez via l’API REST et avez donc besoin d’un client sup­plé­men­taire. Il est re­com­mandé d’utiliser Kibana pour cela (également une offre open source gratuite d’Elastic). Avec ce programme, vous pouvez utiliser Elas­tic­search di­rec­te­ment dans votre na­vi­ga­teur. Pour ce faire, il vous suffit de vous rendre sur 'http://localhost:5601/' et d’accéder à une interface uti­li­sa­teur graphique. Vous pourrez en savoir plus sur la manière d’installer et de con­fi­gu­rer Kibana dans notre tutoriel pour Kibana. Dans Kibana et tout autre client, vous pouvez utiliser les méthodes HTTP suivantes pour envoyer des commandes à votre recherche plein texte : PUT, GET, POST et DELETE.

Index

Dans un premier temps, vous devez d’abord créer votre indexe et y ajouter des données. Vous pouvez utiliser deux méthodes HTTP dif­fé­rentes pour cela : POST et PUT. Utilisez PUT si vous voulez spécifier un ID spé­ci­fique pour l’entrée. Avec POST, Elas­tic­search crée lui-même un iden­ti­fiant. Dans notre exemple, nous aimerions établir une bi­blio­gra­phie. Chaque entrée doit contenir le nom de l’auteur, le titre de l’œuvre et l’année de pu­bli­ca­tion.

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

Si vous souhaitez utiliser l’entrée de cette façon, vous devez utiliser la console Kibana. Toutefois, si vous ne souhaitez pas utiliser ce logiciel, vous pouvez utiliser cURL. Au lieu de la commande pré­cé­dente, vous devrez entrer ce qui suit dans la ligne de commande :

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

Dans ce qui suit, nous vous montrons seulement le code pour Kibana, mais il peut être fa­ci­le­ment transféré dans la syntaxe de cURL.

Si vous avez tout saisi cor­rec­te­ment, Elas­tic­search doit renvoyer les in­for­ma­tions suivantes au début du message :

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

À ce stade, Elas­tic­search peut main­te­nant trouver un index avec le nom bi­blio­gra­phy et le type novels. Comme nous avons utilisé la méthode POST, Elas­tic­search génère au­to­ma­ti­que­ment un iden­ti­fiant unique pour notre entrée. L’entrée est ac­tuel­le­ment en première version et a été créée récemment.

Note

Dans Elas­tic­search, un type (_type) se référait au­pa­ra­vant à une sorte de sous-catégorie. Il était alors possible de regrouper plusieurs types sous un même index. Cependant, cela a conduit à des problèmes divers et Elastic prévoyait donc de ne plus les utiliser. Avec la version 6.x _type est toujours inclus, mais il n’est plus possible de ras­sem­bler plusieurs types sous un même index. A partir de la version 7.0 il est prévu de supprimer tous les types, comme l’ex­pli­quent les dé­ve­lop­peurs dans leur blog.

Vous pouvez également utiliser PUT pour donner un ID spé­ci­fique à votre entrée. Ce dernier est défini dans la première ligne du code. Vous avez également besoin de PUT si vous voulez modifier une entrée existante.

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

La sortie suivante est très similaire à ce que nous obtenons avec la méthode POST, mais Elas­tic­search nous donne l’ID que nous avons fourni à la première ligne de l’entrée. La spé­ci­fi­ca­tion est toujours du même ordre : _index/_type/_id.

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

Avec la commande PUT et l’ID unique, nous pouvons aussi changer les entrées :

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

Puisque l’entrée avec l’iden­ti­fiant 1 existe déjà, Elas­tic­search la modifie seulement au lieu d’en créer une nouvelle. Cela se reflète également dans l’output :

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

Le numéro de version est monté à 2 et, donc pour result on obtient updated au lieu de created. Bien sûr, on peut faire la même chose avec un iden­ti­fiant aléatoire créé par Elas­tic­search - mais compte tenu de la longueur des ca­rac­tères, un travail sup­plé­men­taire complique encore un peu plus les choses. Avec la procédure, Elas­tic­search écrase tout sim­ple­ment une entrée si, par exemple, il y a une confusion avec les numéros ID. Pour éviter un écra­se­ment in­vo­lon­taire, vous pouvez utiliser le terminal _create :

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

Comme l’entrée avec l’iden­ti­fiant 1 existe déjà dans l’index, un message d’erreur s’affiche.

Si vous apportez des mo­di­fi­ca­tions à une entrée comme décrit, vous créez à pro­pre­ment parler une entrée en­tiè­re­ment nouvelle et devez donc saisir toutes les données in­té­gra­le­ment. Autrement, vous pouvez également n’intégrer que les mo­di­fi­ca­tions de l’entrée existante. Pour ce faire, utilisez la commande _update :

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

Nous avons main­te­nant ajouté un champ sup­plé­men­taire à l’entrée et modifié un champ existant sans supprimer les autres, mais cela qu’au premier plan. En arrière-plan, Elas­tic­search a néanmoins créé la nouvelle entrée complète, mais a du coup aussi ajouté les contenus déjà existants in­dé­pen­dam­ment.

En principe, nous avons jusqu’à présent sim­ple­ment écrit une entrée dans une base de données et nous pouvons main­te­nant également la récupérer di­rec­te­ment ; pour cela, la méthode GET est né­ces­saire.

GET bibliography/novels/1

Vous pouvez également afficher l’entrée dans votre na­vi­ga­teur :

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

Dans la sortie, Elas­tic­search affiche tous les détails de notre entrée :

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

En plus des in­for­ma­tions déjà connues, vous trouverez les champs du document sous _source. Elas­tic­search nous informe aussi qu’une entrée a bien été trouvée. Si vous tentez d’appeler une entrée inexis­tante, aucun message d’erreur n’apparaît. En revanche, Elas­tic­search affiche "found": false et aucune entrée n’est à trouver sous _source.

Vous avez également la pos­si­bi­lité de ne retirer que certaines in­for­ma­tions de la base de données. Supposons que vous ayez non seulement inclus des données bi­blio­gra­phiques dans votre index, mais aussi le texte complet de chaque roman en­re­gis­tré. Cela s’af­fi­che­rait également avec une simple requête GET. Supposons toutefois que vous ne vous in­té­res­siez ac­tuel­le­ment qu’au nom de l’auteur et au titre de l’œuvre ; alors il faut faire une requêter ciblée :

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

Si les mé­ta­don­nées d’une entrée ne vous in­té­res­sent pas, vous pouvez également n’afficher que le contenu :

GET bibliography/novels/1/_source

Supposons que vous ne vouliez pas appeler une seule entrée dans votre index, mais plusieurs. Elas­tic­search a im­plé­menté _mget (pour multi-get) à cette fin. Si vous l’utilisez, spécifiez une série d’iden­ti­fiants multiples :

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

Même si une entrée n’existe pas encore, la demande complète n’échoue pas. Toutes les données exis­tantes vous seront affichées. Quant aux données man­quantes, Elas­tic­search explique ne pas pouvoir les retrouver.

La sup­pres­sion d’une entrée fonc­tionne de la même manière que pour l’appeler. Toutefois, au lieu d’utiliser GET, vous uti­li­se­rez DELETE :

DELETE /bibliography/novels/1

Dans la sortie suivante, Elas­tic­search vous informe qu’il a trouvé l’entrée sous l’iden­ti­fiant spécifié :

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

De plus, le programme augmente le numéro de version d’une unité. Deux raisons à cela :

  1. Elas­tic­search marque l’entrée seulement comme supprimée et ne la supprime pas di­rec­te­ment du disque dur. L’entrée ne dis­pa­raî­tra qu’au fur et à mesure de l’in­dexa­tion.
  2. Lorsque vous tra­vail­lez avec des index dis­tri­bués sur plusieurs nœuds, une gestion détaillée des versions est ex­trê­me­ment im­por­tante. Par con­sé­quent, Elas­tic­search marque chaque mo­di­fi­ca­tion comme une nouvelle version, ce qui inclut donc aussi la demande de sup­pres­sion.

Vous pouvez également apporter des mo­di­fi­ca­tions uni­que­ment à un numéro de version spé­ci­fique que vous con­nais­sez. S’il existe déjà une version plus récente dans le cluster que celle que vous avez spécifiée, la tentative de mo­di­fi­ca­tion entraîne un message d’erreur.

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

En outre, vous pouvez non seulement appeler plusieurs entrées à la fois, mais également en créer ou en supprimer plusieurs avec _bulk. Pour cela, Elas­tic­search utilise une syntaxe lé­gè­re­ment modifiée.

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

Chaque commande a sa propre ligne. Vous spécifiez d’abord l’action à exécuter (create, index, update, delete). En outre, vous spécifiez également quelle entrée vous voulez créer et où. Avec une commande Bulk, il est aussi possible de tra­vail­ler dans plusieurs index. Pour ce faire, vous devez laisser le chemin vers POST vide et attribuer un chemin différent à chaque action. Lorsque vous créez des entrées, vous devez également spécifier un request body dans une nouvelle ligne. Il contient alors le contenu de l’entrée. L’ins­truc­tion DELETE n’exige au­cu­ne­ment un request body, puisque l’entrée entière est supprimée.

Jusqu’à main­te­nant, nous avons toujours donné un même contenu dans les exemples, et ce peu importe le champ : Elas­tic­search a in­ter­prété toutes les in­for­ma­tions comme une chaîne de ca­rac­tères cohérente. Toutefois, ce n’est pas toujours le cas dans tous les champs. C’est pourquoi Elas­tic­search possède un mapping. Ce dernier détermine comment les al­go­rithmes doivent in­ter­pré­ter une entrée. Vous pouvez utiliser le code suivant pour afficher le mapping ac­tuel­le­ment utilisé dans votre index :

GET bibliography/novels/_mapping

Tous les champs sont affectés aux types text et keyword. Elas­tic­search reconnaît toutefois 6 types de données de base et encore plus de domaines spé­ci­fiques. Les 6 prin­ci­paux types sont divisés en partie en d’autres sous-ca­té­go­ries :

  • String : il concerne à la fois text et keyword. Bien que Keywords est pris en compte comme cor­res­pon­dance exacte, Elas­tic­search part du principe qu’un texte doit être analysé avant de pouvoir être utilisé.
  • Numeric : Elas­tic­search reconnaît des valeurs nu­mé­riques qui diffèrent surtout par leur étendue. Par exemple, alors que le type byte peut avoir des valeurs comprises entre -128 et 127, on con­si­dé­rera avec long une four­chette allant de -263 à 263-1.
  • Date : une date peut être spécifiée au jour ou à l’heure. Vous pouvez également spécifier une date sous forme de temps Unix, c’est-à-dire en secondes ou mil­li­se­condes depuis le 1er janvier 1970.
  • Boolean : les champs formatés boolean peuvent avoir une valeur vraie (true) ou fausse (false).
  • Binary : vous pouvez insérer des données binaires dans ces champs. Pour cela, utilisez l’encodage Base64.
  • Range : il permet de spécifier une plage. Elle peut se situer entre deux valeurs nu­mé­riques, deux données ou même entre deux adresses IP.

Ce ne sont là que les prin­ci­pales ca­té­go­ries que vous uti­li­se­rez pro­ba­ble­ment le plus souvent. Pour d’autres types, vous pouvez consulter la do­cu­men­ta­tion Elas­tic­search. Les dif­fé­rents types se dis­tin­guent surtout par le fait qu’ils sont soit en valeur exacte (exact-value), soit en texte intégral (full-text). Elas­tic­search prend donc le contenu du champ comme une entrée précise ou comme un contenu qui doit d’abord être traité. Au cours du mapping, l’analyse est également im­por­tante. L’analyse du contenu est divisée en :

Elas­tic­search utilise donc des analysers. Si vous incluez bien un document dans l’index et si vous avez bien effectué votre mapping, tous les contenus seront inclus cor­rec­te­ment dans l’index inversé. Pour pouvoir utiliser le mapping vous-même, vous devez créer un tout nouvel index. Le mapping des champs existants n’est pas possible.

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

Nous avons défini les deux champs author et title comme text et donc comme full-text. Ils ont donc besoin d’un analyseur approprié. Alors que nous four­nis­sons l’analyseur standard pour le champ titre du roman, nous choi­sis­sons l’analyseur moins complexe Simple Analyzer pour le nom de l’auteur. L’année de pu­bli­ca­tion, en revanche, est définie comme date, et donc comme exact-value. Comme Elas­tic­search prend par défaut un format année, mois et jour, nous ef­fec­tuons une mo­di­fi­ca­tion afin de le limiter à l’année.

La recherche

Dans le chapitre précédent, nous avons utilisé Elas­tic­search et son index surtout comme base de données. Cependant, l’intérêt d’Elas­tic­search est de pouvoir procéder à des re­cherches en texte intégral. Cela signifie qu’au lieu de saisir l’iden­ti­fiant d’un document et d’appeler l’entrée, nous avons redéfini Elas­tic­search afin de pouvoir re­cher­cher spé­ci­fi­que­ment un contenu. Pour le moteur de recherche, le programme a fourni le paramètre _search. Ainsi, en com­bi­nai­son avec la méthode GET, vous pouvez, par exemple, afficher toutes les entrées :

GET bibliography/novels/_search
Remarque

Pour les requêtes plus complexes, _search utilise un body entre accolades. Cependant, certains serveurs HTTP ne le prévoit pas pour la méthode GET. Par con­sé­quent, les dé­ve­lop­peurs con­si­dè­rent que ces demandes doivent fonc­tion­ner également comme POST.

Vous pouvez également laisser le chemin vide pour re­cher­cher tous les index existants. Dans l’output, vous trouverez les in­for­ma­tions in­té­res­santes sous hits :

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

Toutes les autres entrées de notre index sont également listées dans l’output (et ne sont omises ici que par souci de clarté). Le retour d’Elas­tic­search nous fournit deux in­for­ma­tions sup­plé­men­taires en plus du contenu réel, qui peuvent nous aider à com­prendre la recherche en texte intégral :

  • Hits : chaque entrée qui répond aux critères de recherche sera con­si­dé­rée comme une cor­res­pon­dance par Elas­tic­search. Le programme affiche également le nombre de hits. Puisque dans notre exemple il y a 3 entrées dans l’index, on trouve "total": 3.
  • Score : Elas­tic­search indique la per­ti­nence de l’entrée par rapport à notre requête. Comme dans notre exemple nous avons fait la recherche de toutes les con­tri­bu­tions, elles ont toutes le même score de 1. Les entrées sont triées dans les résultats de recherche par ordre dé­crois­sant en fonction de leur per­ti­nence.

De plus, Elas­tic­search fournit des in­for­ma­tions sur le nombre de shards impliqués dans les résultats de la recherche, le nombre de mil­li­se­condes que la recherche a pris et si un délai d’attente a été né­ces­saire.

Par défaut, Elas­tic­search n’affiche que les dix premiers résultats de recherche. Toutefois, vous pouvez modifier la con­fi­gu­ra­tion en dé­fi­nis­sant des pa­ra­mètres :

  • Size : combien de résultats doivent être affichés ?
  • From : combien d’entrées le programme doit-il ignorer avant de les afficher ?

Si vous avez vu seulement les 10 premiers résultats de recherche et que vous voulez vi­sua­li­ser encore les 15 suivants, il sera né­ces­saire d’utiliser la com­bi­nai­son de deux pa­ra­mètres :

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

Elas­tic­search distingue deux types de recherche dif­fé­rents. D’une part, il utilise une version Lite, d’autre part une variante plus complexe qui fonc­tionne avec le Query DSL - une langue de requête spé­ci­fique. Avec la version Lite, vous saisissez votre recherche à l’aide d’une simple chaîne de ca­rac­tères di­rec­te­ment :

GET bibliography/novels/_search?q=atwood

Il est néanmoins également possible d’effectuer une recherche qu’au sein d’un champ précis :

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

Si vous voulez combiner plusieurs critères de recherche, utilisez le caractère « + ». Utilisez à l’inverse le caractère « - » pour exclure certains critères. Si vous utilisez ces opé­ra­teurs, vous devez toutefois utiliser un codage en pour­cen­tage dans la demande de recherche :

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

La syntaxe des query string d’Elas­tic­search offre encore plus de sub­ti­li­tés pour per­son­na­li­ser sa recherche. Dans la do­cu­men­ta­tion du logiciel, les dé­ve­lop­peurs d’Elastic ont résumé tous les éléments es­sen­tiels : phrases exactes, champs vides ou espaces réservés.

Cette variante de recherche est bien adaptée pour les requêtes simples, mais pour des tâches plus complexes, la procédure Lite peut ra­pi­de­ment échouer : le risque de faire une erreur dans la longue chaîne de ca­rac­tères est trop élevé. C’est pourquoi Elas­tic­search offre avec Query DSL une procédure plus con­for­table. Le point de départ d’une recherche est alors le paramètre query auquel on associe un match query :

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

Le résultat nous montre toutes les entrées qui con­tien­nent le terme « allende » dans le champ author. Il nous dit aussi que l’analyse du mapping a fonc­tionné, car Elas­tic­search ignore les ma­jus­cules et les mi­nus­cules. Pour afficher toutes les entrées, vous pouvez utiliser match_all en plus de la variante simple déjà in­tro­duite :

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

Le contraire de cette recherche est match_none. Par ailleurs, Elas­tic­search donne aussi la pos­si­bi­lité de re­cher­cher dans plusieurs champs avec un seul terme de recherche :

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

Pour permettre les demandes complexes, vous pouvez également combiner plusieurs termes de recherche entre eux et les noter dif­fé­rem­ment. Cela ouvre les pos­si­bi­li­tés de trois manières dif­fé­rentes :

  • must : le terme doit ap­pa­raître.
  • must_not : le terme ne doit pas ap­pa­raître.
  • should : si ce terme apparaît, la per­ti­nence est in­cré­men­tée dans les résultats de recherche.

Dans la pratique, on le combine avec une requête bool :

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

Vous pouvez également étendre votre recherche en ajoutant un filtre. Ceci vous permet de définir des critères qui limitent les résultats de la recherche :

{
	"query": {
"bool": {
		"must": {
			"match": {
				"title": "la"
			}
},
		"filter": {
			"range": {
				"year": {
					"gte": "1950",
					"lt": "2000"
				}
			}
		}
	}
}
}

Dans l’exemple précédent, nous avons filtré selon une période de temps : seules les entrées publiées entre 1950 et 2000 doivent être affichées.

En résumé

Avec cet outil, vous disposez de tout ce dont vous avez besoin pour mettre en œuvre une recherche en texte intégral sur votre site. Elas­tic­search propose cependant encore d’autres méthodes pour affiner votre recherche et la rendre plus per­for­mante. Pour en savoir plus, consultez le site officiel d’Elastic. Si vous souhaitez étendre la recherche plein texte, vous pouvez également créer vos propres scripts avec d’autres langues telles que Groovy et Clojure.

Avantages et in­con­vé­nients d’Elas­tic­search

Elas­tic­search peut cons­ti­tuer une recherche en texte intégral puissante. Elle offre en effet de nombreux avantages, également par rapport à son con­cur­rent direct Apache Solr.

Avantages In­con­vé­nients
Open Source Elastic fait figure de Ga­te­kee­per
Rapide et stable
Évo­lu­tif­Flexible et dynamique
Nombreux modules de pro­grammes prêts à l’emploi (Analyzer, recherche plein texte...)
Mise en œuvre facile grâce à Java, JSON et REST-API
Aller au menu principal