Tutoriel pour découvrir ElasticSearch : moteur de recherche taillé pour le Cloud

| Khanh Tuong Maudoux (Soat) | Soat |

Lors de cette conférence de 55 minutes qui a eu lieu jeudi 19 avril 2012 pendant cette première organisation de Devoxx France 2012, David Pilato (@dadoonet) nous a présenté ElasticSearch.

Cette rétrospective de Devoxx France 2012 a été réalisée par Khanh Tuong Maudoux, consultant Soat et reporters Developpez.com pour Devoxx France 2012.

Pour réagir au contenu de cet article, un espace de dialogue vous est proposé sur le forum Commentez . ♪

- Titre : Tutoriel pour découvrir ElasticSearch : moteur de recherche taillé pour le Cloud

- Auteurs : Khanh Tuong Maudoux (Soat), Soat

- Parution : 4 mai 2012

- Licence : Copyright ® 2012 SOAT. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Concepts, besoins et définition d'un moteur de recherche

- III. ElasticSearch : concepts et fonctionnement

- IV. ElasticSearch : Utilisation

- V. Collecte de données dans ElasticSearch

- VI. Analyse des résultats d'ElasticSearch

- VII. Architecture d'ElasticSearch

- VIII. Conclusion

- IX. Remerciements

I - Introduction

Cette rétrospective de la présentation de David Pilato lors de Devoxx France 2012 dont le titre était : « ElasticSearch : Moteur de recherche HTTP/REST/JSON, cloud, NoSQL, Scalable » s'appuiera sur le même plan que David a donné à sa conférence. Ce compte-rendu, que j'essaierai de retranscrire de manière la plus exhaustive possible, s'articulera donc autour des parties suivantes :

- définition d'un moteur de recherche ;

- concepts d'ElasticSearch ;

- utilisation d'ElasticSearch ;

- architecture d'ElasticSearch.

II - Concepts, besoins et définition d'un moteur de recherche

Afin d'introduire les concepts d'un moteur de recherche, David a commencé par rappeler que, dans une grande majorité des cas, les données présentes en base de données ne sont exploitées que lors d'une recherche et qu'elles exploitent, finalement, assez peu les possibilités offertes par les bases de données relationnelles.

En effet, la récupération de données est malheureusement synonyme de requêtes ayant la forme suivante :

SELECT
doc.*, pays.*
FROM
doc, pays
WHERE
doc.pays_code = pays.code AND
doc.date_doc > to_date('2011-12', 'yyyy-mm') AND
doc.date_dic < to_date('2012-01', 'yyyy-mm') AND
lower(pays.libelle) = 'france' AND
lower(doc.commentaire) LIKE '%saisie%' AND
lower(doc.commentaire) LIKE '%david%';

Malheureusement, l'utilisation de like SQL est assez désastreuse du point de vue des performances dès que le nombre de données s'accroît (par exemple, pour 500 000 déclarations, le temps constaté peut attendre les 5 secondes et, au-delà, des dégradations encore plus importantes peuvent se faire sentir).

C'est dans de telles circonstances qu'un moteur de recherche peut s'avérer utile. Un moteur de recherche est composé de deux choses :

- un moteur d'indexation de documents ;

- un moteur de recherche sur les index.

C'est pour cette raison qu'un moteur de recherche est plus adapté à la recherche de données. En effet, alors qu'une base de données a comme rôle principal le stockage de données, un moteur de recherche a pour seuls objectifs l'indexation et la recherche de données, or seul l'utilisateur connaît ses besoins, ses données et ses recherches.

L'adage « Your Data, your Search » fait d'ailleurs office d'un article sur le blog d'ElasticSearch.

III - ElasticSearch : concepts et fonctionnement

Une fois les bases posées, David est entré dans le vif du sujet en introduisant ElasticSearch qui est un moteur de recherche s'appuyant sur Apache Lucene et reposant sur les principes portés par la mouvance NoSQL, tout en s'appuyant sur les standards HTTP, REST et JSon.

De plus, ElasticSearch dispose des points forts suivants :

- simple : aucune configuration n'est nécessaire pour utiliser ElasticSearch ;

- efficace : le démarrage d'un nœud ElasticSearch suffit à l'intégrer à l'écosystème, et ainsi bénéficier de la réplication et du dimensionnement automatique ;

- puissant : en s'appuyant sur Apache Lucene, les traitements sont parallélisés entre les différents nœuds ;

- complet : il propose un grand nombre de fonctionnalités (analyse et facettes, percolation, rivière, plugins…).

Concernant le stockage des données, ElasticSearch s'appuie sur trois concepts :

- le document : c'est l'objet qui permet de représenter une donnée (au sens NoSQL du terme). Par contre, pour ce faire, il est nécessaire de penser recherche et de penser document en oubliant toute notion de SGBDR et donc de jointure ;

- le type : le type permet de regrouper des documents de même type ;

- l'index : c'est l'espace logique de stockage des documents dont les types sont fonctionnellement communs ;

{
"text": "Bienvenu à la conférence #elasticsearch pour #devoxxfr",
"created_at": "2012-04-06T20:45:36.000Z",
"source": "Twitter for android",
"truncated": false,
"retweet_count": 0,
"hashtag": [
{
"text": "elasticsearch",
"start": 27,
"end": 40
},
{
"text": "devoxxfr",
"start": 47,
"end": 55
}
],
"user": {
"id": 51172224,
"name": "David Pilato",
"screen_name": "dadoonet",
"location": "France",
"description": "Soft Architect, Project Manager, Senior Developper"
}
}

IV - ElasticSearch : Utilisation

Après avoir introduit ElasticSeach, David a ensuite mis l'accent sur le côté interaction avec le moteur de recherche ElasticSearch via ses API REST : à l'aide des verbes HTTP comme GET, POST, PUT et DELETE sur une URL donnée :

http://<host>:<port>/[index]/[type]/[_action/id]

Par exemple, voici ce que l'on peut trouver.

- pour enregistrer une donnée dans ElasticSearch :

curl -XPUT http://localhost:9200/twitter/tweet/1

- pour récupérer une donnée dans ElasticSearch :

curl -XGET http://localhost:9200/twitter/tweet/1

- pour supprimer une donnée d'ElasticSearch :

curl -XDELETE http://localhost:9200/twitter/tweet/1

- pour rechercher une donnée dans ElasticSearch :

curl -XGET http://localhost:9200/twitter/tweet/_search

curl -XGET http://localhost:9200/twitter/_search

curl -XGET http://localhost:9200/_search

curl -XGET http://localhost:9200/twitter/tweet/_search?q=elasticsearch

ce qui donne :

{
"took": 24,
"time_out": false,
"_shards": {
"total": 5,
"sucessful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.227,
"hits": [
{
"_index": "twitter",
"_type": "tweet",
"_id": "1",
"_score": 0.227,
"_source": {
"text": "Bienvenue à la conférence #elasticsearch pour #devoxxfr, "created_at": "2012-04-06T20:45:36.000Z", "source": "Twitter for android", ...
}
}
]
}
}

Il est possible de constater que le nombre de documents trouvé est fourni (élément total) ainsi que la pertinence du résultat (élément _score). Cette pertinence est calculée suivant le nombre d'occurrences plus ou moins exactes de chaque terme dans un document.

De même, on peut constater qu'ElasticSearch autoadapte les documents puisqu'il n'est pas nécessaire d'indiquer le type de la donnée, mais qu'il est, toutefois, possible de définir son propre mapping.

- pour récupérer les métadonnées d'un document d'ElasticSearch :

curl -XGET http://localhost:9200/twitter/_status

- pour indexer un document dans ElasticSearch :

curl -XPUT localhost:9200/twitter/tweet/1 -d '
{
"text": "Bienvenu à la conférence #elasticsearch pour #devoxxfr",
"created_at": "2012-04-06T20:45:36.000Z",
"source": "Twitter for android",
"truncated": false,
"retweet_count": 0,
"hashtag": [
{
"text": "elasticsearch",
"start": 27,
"end": 40
},
{
"text": "devoxxfr",
"start": 47,
"end": 55
}
],
"user": {
"id": 51172224,
"name": "David Pilato",
"screen_name": "dadoonet",
"location": "France",
"description": "Soft Architect, Project Manager, Senior Developper"
}
}'

ce qui donne :

{
"ok": true,
"_index": "twitter",
"_type": "tweet",
"_id": "1"
}

curl -XGET http://localhost:9200/twitter/tweet/_search?q=elasticsearch&from=10&size=10

Il est cependant à noter qu'ElasticSearch ne renvoie que les 10 premiers résultats, mais qu'il est possible de naviguer dans les résultats à l'aide des options from, exemple :

curl -XGET http://localhost:9200/twitter/tweet/_search?q=elasticsearch&from=10&size=10

De plus, à cela s'ajoute la possibilité d'utiliser des options de recherche avancée à l'aide du QueryDSL (matchAll, queryString, prefix - utile, entre autres, pour permettre des cas d'usage d'autocomplétion…).

V - Collecte de données dans ElasticSearch

Concernant le peuplement des données dans ElasticSearch, il est possible d'utiliser des rivières qui permettent de déverser des documents dans ElasticSearch.

David nous en a alors présenté six types :

- CouchDB River ;

- MongoDB River ;

- Wikipedia River ;

- Twitter River ;

- RabbitMQ River ;

- et RSS River.

VI - Analyse des résultats d'ElasticSearch

Afin d'analyser les résultats remontés par ElasticSearch, il est possible d'utiliser des facettes qui permettent d'agréger les données en s'appuyant sur les requêtes de recherches.

Pour faire simple, une facette peut être assimilée à une sorte de vue permettant de donner un aspect fonctionnel aux données récupérées (ie. par exemple, de permettre une navigation par facette).

La facette la plus simple est la facette term qui permet de rechercher certains termes présents dans un document.

Par exemple, si on dispose des données suivantes dans ElasticSearch :

curl -X POST "http://localhost:9200/articles/article" -d '{"title" : "One", "tags" : ["foo"]}'
curl -X POST "http://localhost:9200/articles/article" -d '{"title" : "Two", "tags" : ["foo", "bar"]}'
curl -X POST "http://localhost:9200/articles/article" -d '{"title" : "Three", "tags" : ["foo", "bar", "baz"]}'

alors effectuer une recherche de la manière suivante, en utilisant une facette de type term :

curl -X POST "http://localhost:9200/articles/_search?pretty=true" -d '
{
"query": {
"query_string": {
"query": "T*"
}
},
"facets": {
"tags": {
"terms": {
"field": "tags"
}
}
}
}

fourni le résultat suivant :

"facets" : {
"tags": {
"_type": "terms",
"missing": 0,
"total": 5,
"other": 0,
"terms": [
{
"term": "foo",
"count": 2
},
{
"term": "bar",
"count": 2
},
{
"term": "baz",
"count": 1
}
]
}
}

David a ensuite montré quelques-unes des facettes existantes :

- Date Histogram ;

- Ranges.

VII - Architecture d'ElasticSearch

Après avoir introduit les différents concepts apportés par ElasticSearch ainsi que différentes manières de l'utiliser, David a ensuite mis l'accent sur quelques-uns des concepts d'architecture utilisés par le moteur de recherche ElasticSearch, à savoir :

- nœud (node) qui correspond à une instance d'ElasticSearch ;

- cluster qui correspond à un ensemble de nœuds ;

- partition (shard) qui permet de découper un index en plusieurs parties pour y distribuer les documents ;

- réplication (replica) qui correspond à une recopie d'une partition en une ou plusieurs copies dans l'ensemble du cluster ;

- partition primaire (primary shard) qui correspond à la partition élue principale dans l'ensemble du cluster. C'est là que se fait l'indexation par Lucene. Il n'y en a qu'une seule par shard dans l'ensemble du cluster ;

- partition secondaire (secondary shard) qui sont les partitions secondaires stockant les réplicas des partitions primaires.

En fait, lors de la création de l'index, il est possible de préciser à ElasticSearch le nombre de shards ainsi que le nombre de réplicas. Lors de l'ajout ou de suppression de nœuds dans le cluster, ElasticSearch réalloue dynamiquement, c'est-à-dire que le sharding est alors distribué automatiquement.

Le gros travail de configuration d'ElasticSearch revient donc à trouver le bon équilibre entre le nombre de nodes, de shards et de replicas.

Concernant la recherche sur des documents présents dans un cluster disposant de plusieurs nœuds, l'indexation est faite sur le nœud primaire puis est répercutée sur les autres nœuds du cluster. Dans ce cas, la recherche a alors lieu sur l'ensemble des nœuds avec une phase d'agrégation qui s'effectue alors sur le nœud sur lequel la requête de recherche a été effectuée.

Enfin, David a conclu cette partie en précisant qu'ElasticSearch gérait le fail over de manière totalement transparente pour l'utilisateur et qu'à titre indicatif, pour un total de cinq clusters, il était possible de traiter environ cinq milliards de documents.

VIII - Conclusion

En conclusion, David Pilato a présenté la communauté d'ElasticSearch.

À noter que ce petit compte-rendu n'a fait mention ni des projets sur lesquels David a utilisé ElasticSearch ni de la démo dont il nous a gratifié.

Pour ma part, j'ai trouvé cette session très bien menée et très instructive quant aux différentes notions utilisées par ElasticSearch et aux différentes façons de l'utiliser (au sens client du terme). Je la conseille donc à tous ceux qui souhaiteraient en apprendre plus sur ElasticSearch dès qu'elle sera disponible sur parleys.com.

Cependant, j'ai juste un petit regret concernant le fait que David ne soit pas rentré plus profondément dans la gestion du fail over du produit.

Enfin, pour conclure ce petit retour, les slides de la présentation sont déjà disponibles ici.

IX - Remerciements

Cet article a été publié avec l'aimable autorisation de la société Soat.

Nous tenons à remercier jacques_jean pour sa relecture attentive de cet article et Mickael Baron pour la mise au gabarit.