Elasticsearch en 10min

By | 7 décembre 2013

elastic-searchCette semaine, une mission qui m’a été confiée, était de trouver une solution pour catégoriser de manière automatique des articles. Je me suis donc naturellement tourné vers Elasticsearch, produit que je connais uniquement de nom car très populaire en ce moment.

Je pars donc à la découverte d’Elasticsearch.

Introduction

Pour expliquer de manière simple, Elasticsearch est un moteur de recherche open source.

Avant de partir tête baissée dans le code, il y a une chose à savoir. ES classe les documents par Index et par Type. Les Index peuvent être comparés à la base de données pour un SGDR, et le Type à une table.

Je ne vais pas rentrer dans les détails de ce qu’est un Index ou un Type. Premièrement car mes connaissances de ce serveur sont très limitées, et surtout le but de cet article est uniquement de montrer la simplicité de mise en place d’un tel moteur.

Installation d’Elasticsearch

Commençons par son installation (serveur Debian).

Avant tout chose, il faut que Java soit installé sur notre serveur pour faire fonctionner Elasticsearch.

$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java7-installer

Maintenant que Java est installé nous pouvons installer ES.

$ wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-0.90.7.deb
$ dpkg -i elasticsearch-0.90.7.deb
$ update-rc.d elasticsearch defaults
$ /etc/init.d/elasticsearch start

API PHP

Elasticsearch fournit un client PHP, et vu qu’ils ont bien fait les choses nous pouvons l’installer avec composer:

{
    "require": {
        "elasticsearch/elasticsearch": "~0.4"
    }
}

Indexation

Nous voilà donc prêt à jouer avec Elasticsearch. La première étape va être l’indexation de documents.

$params = array();

$client = new Elasticsearch\Client();

$article['index'] = 'blog';
$article['type']  = 'article';
$article['ttl']   = 10;
$article['body']  = array(
    'title' => 'Premier pas avec ES',
    'desc' => 'ES est un moteur de recherche simple à mettre en place !'
);

$result = $client->index($article);
Array
(
    [ok] => 1
    [_index] => blog
    [_type] => article
    [_id] => k_F51gpqQQ-MoRpiK0PdMw
    [_version] => 1
)

Comme nous l’avons vu précédemment, ES classe ses articles de cette manière /index/type/[id].

Pour reprendre l’exemple ci-dessus, nous avons donc indexer un document de type article dans l’index blog. Les Index et les Type vont être créés automatiquement si ils n’existent pas. Ces 2 champs sont obligatoires pour indexer un document.

Les champs contenus dans body sont le contenu de notre article, la structure est libre.

Comme vous avez pu le constater, ES a généré un id pour notre document (« k_F51gpqQQ-MoRpiK0PdMw »), mais nous aurions pu lui fournir notre propre id ($article[‘id’] = 1).

La dernière chose importante est le numéro de version de l’article, cette version sera incrémentée à chaque fois nous indexons un même article, en précisant donc l’id.

Recherche

Pour notre première recherche nous allons récupérer un article par son identifiant.

$params = array();
$params['index'] = 'blog';
$params['type']  = 'article';
$params['id']    = 1;

$article = $client->get($params);
print_r($article);
Array
(
    [_index] => blog
    [_type] => article
    [_id] => 1
    [_version] => 2
    [exists] => 1
    [_source] => Array
        (
            [title] => Ceci est mon titre
            [desc] => Ceci est la description de mon article
        )

)

Comme vous l’avez certainement remarqué, le contenu de notre article se trouve dans _source, pour le reste rien de nouveau. Si nous voulons uniquement récupérer le contenu de l’article sans les méta données nous pouvons appeler la méthode getSource($params).

Continuons par une recherche du nombre de documents indexés:

$params = array();
$params['index'] = 'blog';
$article['type'] = 'article';

$result = $client->count($params);
print_r($result);
Array
(
    [count] => 26
    [_shards] => Array
        (
            [total] => 5
            [successful] => 5
            [failed] => 0
        )

)

Une recherche textuelle sur tous les champs de notre document:

$params = array();
$params['index'] = 'blog';
$params['type']  = 'article';
$params['body']['query']['match']['_all'] = 'moteur';

$results = $client->search($params);
print_r($results);
Array
(
    [took] => 9
    [timed_out] =>
    [_shards] => Array
        (
            [total] => 5
            [successful] => 5
            [failed] => 0
        )
    [hits] => Array
        (
            [total] => 35
            [max_score] => 0.26516503
            [hits] => Array
                (
                    [0] => Array
                        (
                            [_index] => blog
                            [_type] => article
                            [_id] => VMl4KT5uR92g_H9s4RABuA
                            [_score] => 0.26516503
                            [_source] => Array
                                (
                                    [title] => Premier pas avec ES
                                    [desc] => ES est un moteur de recherche simple à mettre en place !
                                )
                        )
                )
        )
)

_all signifie que la recherche s’effectuera dans l’ensemble des champs de notre article. Si vous souhaitez limité la recherche à un champ il suffit de remplacer _all par le nom du champ.

WebServices Elasticsearch

Petit paragraphe pour vous dire que cette librairie PHP ne fait qu’appeler le webservices d’Elasticsearch qui écoute sur le port 9200. Ce qui signifie que si vous appeler l’IP de votre serveur sur le port 9200, vous devriez obtenir une réponse au format json.

{
  "ok" : true,
  "status" : 200,
  "name" : "Steel Raven",
  "version" : {
    "number" : "0.90.7",
    "build_hash" : "36897d07dadcb70886db7f149e645ed3d44eb5f2",
    "build_timestamp" : "2013-11-13T12:06:54Z",
    "build_snapshot" : false,
    "lucene_version" : "4.5.1"
  },
  "tagline" : "You Know, for Search"
}

Récupérer un article par son id

http://192.168.*.*:9200/blog/article/1

Récupérer le nombre d’article

http://192.168.*.*:9200/blog/article/_count

…..

Conclusion

Cet article ne présente qu’une infime partie de ce qu’on peut faire avec Elasticsearch. Pour ceux qui souhaiteraient aller plus loin je vous renvoi vers le site officiel (http://www.elasticsearch.org/).

Category: Php