Configuration pour les synonymes

462 views
Skip to first unread message

vgross

unread,
May 15, 2012, 12:20:09 PM5/15/12
to elastics...@googlegroups.com
Bonjour à tous!!

J'essai tant bien que mal de faire marcher elasticsearch pour mes besoins mais je suis malheureusement confronté à un problème de config.
Voila ce que j'ai fait:

J'ai d'abord édité le fichier '/etc/elasticsearch/elasticsearch.yml' avec: 

cluster: 
   name:   mycluster 

index: 
    analysis: 
        analyzer: 
            syns: 
                tokenizer : standard 
                filter : syn_filter 

        filter: 
            syn_filter: 
                type: synonym 
                synonyms_path: /etc/elasticsearch/synonym.txt 

ensuite j'ai édité mon synonym file '/etc/elasticsearch/synonym.txt' avec : 

cool => sympa 


dans mon script 'index.php' , j'utilise https://github.com/nervetattoo/elasticsearch, d'abord j'execute : 

require_once "ElasticSearchClient.php"; 

$transport = new ElasticSearchTransportHTTP("localhost", 9200); 
$search = new ElasticSearchClient($transport, "myindex", "mytype"); 
var_dump($search->index(array('title' => 'My cool document'))); 
var_dump($search->index(array('title' => 'My second cool document'))); 

Résultat : 

array(5) { 
  ["ok"]=> 
  bool(true) 
  ["_index"]=> 
  string(7) "myindex" 
  ["_type"]=> 
  string(6) "mytype" 
  ["_id"]=> 
  string(22) "olRN5Z2WQo61b74MKnp2DQ" 
  ["_version"]=> 
  int(1) 

array(5) { 
  ["ok"]=> 
  bool(true) 
  ["_index"]=> 
  string(7) "myindex" 
  ["_type"]=> 
  string(6) "mytype" 
  ["_id"]=> 
  string(22) "Ly-Q-mISSm2Jt4HnEcaqww" 
  ["_version"]=> 
  int(1) 


Jusque'ici tout va bien et mes deux documents se trouvent bien dans "myindex" 
Ensuite j'execute mon script avec : 

require_once "ElasticSearchClient.php"; 

$transport = new ElasticSearchTransportHTTP("localhost", 9200); 
$search = new ElasticSearchClient($transport, "myindex", "mytype"); 

var_dump($search->search('title:cool')); 
var_dump($search->search('title:sympa')); 

et le résultat est : 

array(5) { 
  ["took"]=> 
  int(2) 
  ["timed_out"]=> 
  bool(false) 
  ["_shards"]=> 
  array(3) { 
    ["total"]=> 
    int(5) 
    ["successful"]=> 
    int(5) 
    ["failed"]=> 
    int(0) 
  } 
  ["hits"]=> 
  array(3) { 
    ["total"]=> 
    int(2) 
    ["max_score"]=> 
    float(0.2972674) 
    ["hits"]=> 
    array(2) { 
      [0]=> 
      array(5) { 
        ["_index"]=> 
        string(7) "myindex" 
        ["_type"]=> 
        string(6) "mytype" 
        ["_id"]=> 
        string(22) "9nPVEj6DT-65KfKuJvJ9QQ" 
        ["_score"]=> 
        float(0.2972674) 
        ["_source"]=> 
        array(1) { 
          ["title"]=> 
          string(16) "My cool document" 
        } 
      } 
      [1]=> 
      array(5) { 
        ["_index"]=> 
        string(7) "myindex" 
        ["_type"]=> 
        string(6) "mytype" 
        ["_id"]=> 
        string(22) "f67TBpqMQimBiBkD5FZv_g" 
        ["_score"]=> 
        float(0.2972674) 
        ["_source"]=> 
        array(1) { 
          ["title"]=> 
          string(23) "My second cool document" 
        } 
      } 
    } 
  } 
  ["time"]=> 
  float(0.0040738582611084) 

array(5) { 
  ["took"]=> 
  int(1) 
  ["timed_out"]=> 
  bool(false) 
  ["_shards"]=> 
  array(3) { 
    ["total"]=> 
    int(5) 
    ["successful"]=> 
    int(5) 
    ["failed"]=> 
    int(0) 
  } 
  ["hits"]=> 
  array(3) { 
    ["total"]=> 
    int(0) 
    ["max_score"]=> 
    NULL 
    ["hits"]=> 
    array(0) { 
    } 
  } 
  ["time"]=> 
  float(0.0020260810852051) 


Je ne comprends pas pourquoi lors de me deuxième requête il ne me ressort pas les document, et ça fait 1 jour que je bloque... :-/

PS: quand je me rend à l' URL : http://192.168.1.35:9200/_analyze?pretty=1&text=cool&analyzer=syns le résultat est le suivant :


  "error" : "ElasticSearchIllegalArgumentException[failed to find analyzer [syns]]", 
  "status" : 400 


Merci de votre aide !

David Pilato

unread,
May 15, 2012, 12:54:53 PM5/15/12
to elastics...@googlegroups.com
Il faut que tu vérifies si ton index a bien été créé avec cette configuration.
http://www.elasticsearch.org/guide/reference/api/admin-indices-get-settings.html

Pour ma part, je préfère envoyer la conf en curl dans tout le cluster plutôt que d'avoir ça dans un fichier.

Donc, essaye de créer un index avec cette conf en curl pour voir si cela change qq chose.

David ;-)
Twitter : @dadoonet / @elasticsearchfr
--
---
Vous pouvez également poster et consulter les réponses en anglais sur le groupe Elasticsearch https://groups.google.com/group/elasticsearch
 
Si vous avez également posté votre question sur la mailing list elasti...@googlegroups.com, merci d'indiquer ici le lien vers cette discussion pour faciliter le suivi.
 
Twitter : @ElasticsearchFR https://twitter.com/#!/ElasticsearchFR
Site web (English) : http://www.elasticsearch.org/

vgross

unread,
May 16, 2012, 4:38:50 AM5/16/12
to elastics...@googlegroups.com
Salut David ! 

Merci de ta réponse ! 

Je pense qu'il y a qqch qui m’échappe car le résultat de la requete "_settings" donne :

{
  "myindex" : {
    "settings" : {
      "index.number_of_shards" : "5",
      "index.number_of_replicas" : "1",
      "index.version.created" : "190399"
    }
  } 
}

De ce que j'ai compris (reprend moi si je me trompe) les shards sont des espèce de partitions, et je ne comprends pas pourquoi il en trouve 5 alors que je n'ai rien spécifier nul part par rapport à ça...
Autre chose, je pense que mon fichier de configuration n'est pas pris en compte cat je ne trouve pas mon analyzer ! 

La documentation du site officiel ainsi que mes recherches ne m'ont malheureusement pas donné plus de solutions...

Connais-tu un site ou je peux trouver des exemples de configuration ou de mise en oeuvre d'un moteur elasticsearch qui prend en compte les synonymes ?  

Jérôme Mainaud

unread,
May 16, 2012, 4:48:08 AM5/16/12
to elastics...@googlegroups.com
Bonjour,

Par défaut, un index est créé avec 5 shards et 1 réplica.
Tu peux préciser une autre valeur par défaut dans le fichier conf/elasticsearch.yml et donner des valeurs spécifiques à un index lors de sa création dans la rubrique settings.

Bonne journée.

--
Jérôme Mainaud
jer...@mainaud.com



--

vgross

unread,
May 16, 2012, 4:55:05 AM5/16/12
to elastics...@googlegroups.com
Ok je comprends mieux alors :-)

Et qu'en est-il de mettre la configuration d'un index dans un fichier de configuration ? 

J'ai édité un fichier elasticsearch.json dans le répertoire '/etc/elastic/search' et il contient les lignes suivantes :

{
    "myindex" : {
        "analysis" : {
            "analyzer" : {
                "synonym" : {
                    "tokenizer" : "whitespace",
                    "filter" : ["synonym"]
                }
            },
            "filter" : {
                "synonym" : {
                    "type" : "synonym",
                    "synonyms_path" : "/etc/elasticsearch/synonym.txt"
                }
            }
        }
    }
}

Mon fichier /etc/init.d/elasticsearch contient lui : 

#! /bin/sh
### BEGIN INIT INFO
# Provides:          elasticsearch
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Starts elasticsearch
# Description:       Starts elasticsearch using start-stop-daemon
### END INIT INFO

ES_HOME=/usr/local/elasticsearch
ES_MIN_MEM=256m
ES_MAX_MEM=2g
DAEMON=$ES_HOME/bin/elasticsearch
NAME=elasticsearch
DESC=elasticsearch
PID_FILE=/var/run/$NAME.pid
LOG_DIR=/var/log/$NAME
DATA_DIR=/var/lib/$NAME
WORK_DIR=/tmp/$NAME
CONFIG_FILE=/etc/$NAME/elasticsearch.json
DAEMON_OPTS="-p $PID_FILE -Des.config=$CONFIG_FILE -Des.path.home=$ES_HOME -Des.path.logs=$LOG_DIR -Des.path.data=$DATA_DIR -Des.path.work=$WORK_DIR"


test -x $DAEMON || exit 0

set -e

case "$1" in
  start)
    echo -n "Starting $DESC: "
    mkdir -p $LOG_DIR $DATA_DIR $WORK_DIR
    if start-stop-daemon --start --pidfile $PID_FILE --startas $DAEMON -- $DAEMON_OPTS
    then
        echo "started."
    else
        echo "failed."
    fi
    ;;
  stop)
    echo -n "Stopping $DESC: "
    if start-stop-daemon --stop --pidfile $PID_FILE
    then
        echo "stopped."
    else
        echo "failed."
    fi
    ;;
  restart|force-reload)
    ${0} stop
    sleep 0.5
    ${0} start
    ;;
  *)
    N=/etc/init.d/$NAME
    echo "Usage: $N {start|stop|restart|force-reload}" >&2
    exit 1
    ;;
esac

exit 0

Et je ne comprends vraiment pas pourquoi la configuration de mon index n'est pas prise en compte ? 

Si qqn pourrait m’éclaircir sur le sujet...

Merci

Jérôme Mainaud

unread,
May 16, 2012, 5:19:39 AM5/16/12
to elastics...@googlegroups.com
Jusqu'à présent, j'ai toujours créé mes index via l'API. (Soit une commande curl, soit via un client.)
C'est le plus simple et la seule garantie d'avoir une définition cohérente.
En fait, je ne comprend pas que tu veuilles faire autrement.

Garder la définition dans un json que tu passes à curl, facilitera ton déploiement. Vouloir le déployer à la main sur les nœuds est un non sens et une source d'erreur. (D'ailleurs, je ne sais même pas si ça marche.)

Toutes choses égales par ailleurs, vois le json de description d'un index comme une commande CREATE TABLE pour une base SQL. Tu peux utiliser un fichier pour jouer et rejouer la commande de création, mais tu de déploie pas ce fichier sur ton serveur de base de données.

Est-ce plus clair ainsi ?

--
Jérôme Mainaud
jer...@mainaud.com



2012/5/16 vgross <vince...@gmail.com>

vgross

unread,
May 16, 2012, 5:33:38 AM5/16/12
to elastics...@googlegroups.com
Déjà, merci de ton aide !

Oui ça me parait plus clair maintenant. En fait pour le moment je suis en phase de test sur ce moteur de recherche pour savoir si il peut coller au cahier des charges de mon projet d'intégration d'un moteur à mon site marchand (gestion des synonymes, etc.)

Pour ce faire j'utilise le client PHP https://github.com/nervetattoo/elasticsearch .

Avec ce client, je n'arrive pas à créer un index avec sa configuration (je m'y prend peut être un peu mal ?).

Penses-tu que ceci est possible avec ce client ? si oui de quelle manière ? la doc sur son github se limite à quelques exemples très basique... 

Jérôme Mainaud

unread,
May 16, 2012, 6:40:20 AM5/16/12
to elastics...@googlegroups.com
Je ne sais pas. Je n'ai jamais utilisé le client PHP.
Avec le client Java, j'ai eu quelques surprises car le JSON doit être présenté un peut différemment.
Mais le client Java est spécial car il utilise le protocole interne du cluster et non l'API REST. (Même si tout est équivalent.)

La création de l'index étant une opération marginale et généralement réalisée par un opérateur. Pourquoi ne pas utiliser curl pour te débloquer ? Ensuite, quand tu auras plus d'assurance avec elasticsearch, tu pourras revenir sur la création de l'index depuis ton client PHP.

La page http://www.elasticsearch.org/guide/reference/api/admin-indices-create-index.html te donnera des exemple.

Fait attention à ne pas confrondre index et mapping. Pour un index, il peut y avoir plusieurs mappings. Tu peux les créer séparément, mais le plus simple est de les créer tous lors de la création de l'index. C'est le mapping qui te permet d'associer un analyser avec un champ. Si tu ne veux qu'un analyseur, il faut que tu le nomme « default ».

D'une façon générale, apprend d'abord à utiliser elasticsearch via son API REST. Ensuite, tu pourras plus facilement comprendre la déclinaison qu'en fait un client spécifique.

--
Jérôme Mainaud
jer...@mainaud.com



--

vgross

unread,
May 16, 2012, 8:19:31 AM5/16/12
to elastics...@googlegroups.com
Ok je comprends !

Je vais m’exercer avec l'API mais avant de continuer je voudrais d'abord éclaircir un concept de base pour bien comprendre la direction à prendre lors de mes tests de l'API...

En gros, je vais rentrer une liste de produit (des fringues) avec pour chacun un id, un nom, une description, un prix, des tailles, etc.. comme toutes les fringues ont la même fiche descriptive, je suppose que je devrai faire un seul mapping pour mon index (dites moi si je me trompe).
L'équipe marketing veut avoir la main sur les synonymes (je leur ferai une interface sur leur espace de gestion qui générera le fichier "synonym.txt" ou se trouve l'ensemble des synonymes).
Donc en fait je voudrai que ce fameux dictionnaire des synonymes soit appliqué, lors d'une recherche, à l'ensemble des champs d'un produit (nom, description, etc.)

Première question : dois-je créer un index avec un type obligatoirement ? style "myindex" et "mytype" ?
Deuxième question : pour les synonymes, si je veux qu'il soit appliqué à tous les champs dois-je nomer mon analyzer default comme tu me l'a indiqué ci dessus ? avec un truc du style : 

$elasticaIndex->create(array(
    'number_of_shards' => 5,
    'number_of_replicas' => 1,
    'analysis' => array(
        'analyzer' => array(
            'default' => array(
                'tokenizer' => 'standard',
                'filter' => 'synonym'
            )
        ),
        'filter' => array(
            'synonym' => array(
                'type' => 'synonym',
                'synonyms_path' => '/etc/elasticsearch/synonym.txt'
            )
        )
    )
), true);

J'utilise maintenant le client https://github.com/ruflin/Elastica  qui est beaucoup plus complet et avec qui j'ai réussi à créer mon index comprenant mon analyzer (qui ne fonctionne pas encore lol)

Merci

Jérôme Mainaud

unread,
May 16, 2012, 9:09:57 AM5/16/12
to elastics...@googlegroups.com
Oui, il faut créer un type.
Si tu ne le fait pas, il sera créé (ainsi que l'index si nécessaire) lorsque tu indexeras ton premier élément.
Si tu n'a qu'un seul format de fiche, tu n'as besoin que d'un type.

Vu ce que tu veux faire, commence par comprendre le fonctionnement d'un analyzer. Notamment son effet sur le contenu indexer et sur la recherche effectuée. Tu verras que rendre le dictionnaire des synonyme modifiables n'est pas une si mince affaire. Il te faudra, soit déployer un grand talent dans sa définition et celle des analyseurs, soit réindexer toutes tes données à chaque modification du dictionnaire.
 
Pour ta deuxième question, l'analyseur par défaut est appliqué à tous les champs qui contiennent du texte, qui sont analysés et dont l'analyseur n'est pas défini.

Pour le définir j'ai un json de description de mon index comme ça:
{
    "settings": {
        "index": {
            "analysis": {
                "analyzer": {
                    "default": {
                        "type": "french",
                        "stopwords": [ 'a' /* ... */ ]                    
                    }
...


--
Jérôme Mainaud
jer...@mainaud.com

vgross

unread,
May 16, 2012, 9:25:09 AM5/16/12
to elastics...@googlegroups.com
Je te remercie grandement pour toutes ces précisions ! 

En fait, vu que le catalogue bouge tous les jours et qu'il comporte à peu près 15 000 entrées, je comptais ré-indexer toutes les données chaque nuit (et donc par la même occasion prendre en compte les modifications du fichier des synonymes).
Si tu penses que je fais fausse route ou que je vais rencontré de lourd problème dans ce que j’entreprends, préviens moi :-)

En gros sur le projet je n'ai aucun budget pour investir dans un moteur de recherche payant, et comme le site à relativement pas mal de trafic, je me suis orienté sur elasticsearch pour des questions de performances...
Après pour définir les différents synonymes, etc. c'est l'équipe marketing qui s'y collera ! 

Bref, j'espère ne pas être en train de faire ce qu'il faut pas ! C'est la première fois que j'aie à mettre en place un moteur de recherche et c'est vrai que je patauge pas mal...

Merci d'avoir pris le temps de m'aider en tout cas, c'est vraiment sympa !

Jérôme Mainaud

unread,
May 16, 2012, 10:55:19 AM5/16/12
to elastics...@googlegroups.com
En fait, tout dépend du volume de tes données et de la difficulté à les indexer. Si tu as 15000 entrées qui viennent d'une base de données, la réindexation nocturne est valable. Si tu avais eu 50 millions de documents PDF, ça vaudrait surement le coup d'étudier une méthode plus subtile.

Ce que je voulais dire, c'est que tu as intérêt  à comprendre le principe de fonctionnement des analyseurs. Mais peut-être est-ce déjà le cas ? Je n'ai pas dit de connaitre tout le catalogue.

--
Jérôme Mainaud
jer...@mainaud.com

vgross

unread,
May 16, 2012, 11:33:03 AM5/16/12
to elastics...@googlegroups.com
Je pense en avoir compris l'utilité dans les grandes lignes...

Si tu as des sites (même en anglais) qui explique bien leurs principes, je suis preneur ! Je pense que tu as raison sur le fait de bien comprendre le fonctionnement avant d'imaginer une quelconque mise en situation, ça évitera de passer de longues heures d’incompréhension pour rien ;-)

vgross

unread,
May 19, 2012, 5:24:44 AM5/19/12
to elastics...@googlegroups.com
Je me réponds à moi même ! 

Je viens de trouver cette présentation vidéo de Lucène et d'Elasticsearch. Au début de la vidéo les principes de Tokenizer, D'analyzer, etc. sont pas mal expliqué ! 


Si jamais ça peut servir...

Karel SUEDILE

unread,
Jun 14, 2012, 2:51:07 PM6/14/12
to elastics...@googlegroups.com
merci pour ce partage, bien utile !

Cependant, qu'utiliseriez-vous pour paramétrer la recherche sur un site e-commerce français ?
Quels tokenizers ? Quels analyzers ?

vgross

unread,
Jun 15, 2012, 8:51:38 AM6/15/12
to elastics...@googlegroups.com
Ben disons que ça dépend des produits et des données que tu indexes...

Moi pour le moment j'utilise un analyzer de type "custom" auquel je met un tokenizer de type "whitespace" et comme filtres "synonym" (liste créée par l'équipe market de ma boite), 'lowercase' et 'asciifolding' pour les accents.

Ce type de config répond pour le moment à mes attentes mais le moteur n'est pas encore en prod car non testé par le marketing (j'ai pas fini le dev). Je viendrai te dire si ça suffisait mais je pense que ça ira :-)

Après je paramètre différent boost pour les différent champs, mais je fais ça au niveau de la requête et non au niveau du mapping.

Le mardi 15 mai 2012 18:20:09 UTC+2, vgross a écrit :
Reply all
Reply to author
Forward
0 new messages