Développer et intégrer un Token Filter dans elasticsearch

Dans cet article, je vais aborder un sujet qui est bien documenté pour Solr, mais moins pour elasticsearch : le développement et l’installation d’un token filter. La structure du projet Maven doit permettre de packager le token filter aussi bien pour Lucene seul, que pour Solr ou elasticsearch.

elasticsearch

Que sont des analyzers ou des token filters ?

Lors du processus d’indexation et de recherche dans Lucene, les données indexées ainsi que les requêtes utilisateurs sont analysées. L’analyse des données est généralement identique lors de l’indexation et de la recherche dans un champ donné (par exemple un titre, un auteur, une date ou position géographique).
L’analyse consiste à appliquer un traitement sur les données ou la requête en fonction des caractéristiques du contenu du champ. Par exemple, s’il s’agit d’un titre, le contenu est généralement tokenisé, puis les tokens sont traités selon la langue (retrait des mots vides, ajout des synonymes, stemmisation). Le processus d’indexation est réalisé par :

  • 0 ou plusieurs “char filter”
  • 1 tokenizer
  • 0 ou plusieurs “token filter”

Les “char filters” ont pour rôle de supprimer ou remplacer des caractères (Mapping char filter) ou des ensembles de caractères dans le flux de données (HTMLStrip char filter ou PatternReplace char filter).

Les tockenizers ont pour rôle de découper (ou pas) le flux de données en termes (généralement les mots d’une phrase).

Les “token filters” ont pour rôle de traitter les tokens produits par le tokenizer pour appliquer des règles liées par exemple à la langue des données (suppression des mots vides, stemmisation, …).

Il est fréquent de devoir mettre en place des token filters “custom” adaptés à des besoins spécifiques ou pour améliorer le fonctionnement de Solr. Il existe de nombreux exemples de token filter “custom” développés par la communauté. Pour l’exemple, j’utiliserai le “auto-phrase-tokenfilter” (https://github.com/bejean/auto-phrase-tokenfilter).

Ce token filter a pour objectif de recréer des expressions en regroupant les mots qu’il aurait été préférable de ne pas découper via le tokenizer car ensembles, ils représentent des concepts concrets. Par exemple, des groupe de termes : “New-York”, “New-York city”, “New-Zealand”, “San Francisco”, « New-Jersey ». Ne pas découper ces concepts permet d’obtenir des résultats de recherche plus précis.

Comme la plupart des exemples que l’on trouve, ce token filter est conçu pour fonctionner non seulement avec Lucene seul, mais également avec Solr. Par contre, il n’est pas prévu pour fonctionner dans elasticsearch. Le but de cet article est d’expliquer comment utiliser ces token filters dans elasticsearch.

Fonctionnement d’un token filter dans Lucene

Un token filter est une classe java. Il s’agit pour l’exemple de la classe AutoPhrasingTokenFilter. Le but ici n’est pas d’expliquer comment est implémenté un token filter mais comment il est “appelé” par l’application qui l’utilise. Voici donc une version simplifiée de la classe pour ce qui concerne son instanciation.

On voit que la classe dispose d’un constructeur avec pour paramètre le flux de données à traiter (un flux de tokens) et des paramètres tels que les phrases que l’on souhaite conserver, un paramètre indiquant si les token avant regroupement doivent être également envoyés dans le flux de sortie. Il y a également une méthode pour positionner un paramètre pour indiquer avec quel caractère joindre les termes regroupés.

Une application java appelle donc ce constructeur et éventuellement la méthode lors de la création de l’objet.

Fonctionnement d’un token filter dans Solr

Pour utiliser un token filter dans un traitement d’analyse, Solr s’appuie sur le type du champ qu’il traite et sur son paramétrage dans le fichier shema.xml

Pour instancier un objet AutoPhrasingTokenFilter, Solr a besoin d’une factory qui dispose en entrée du paramétrage du token filter pour le type en question.

Le constructeur reçoit la configuration du schéma comme paramètre d’entrée, la fonction “create” retourne un objet AutoPhrasingTokenFilter créé avec ces paramètres.

Je ne rentre pas dans le détail de l’utilisation et l’installation d’un token filter dans Solr. Il faut mettre le ou les jar contenant les classes du token filter et de sa factory dans le classpath et définir un type dans schema.xml.

Fonctionnement d’un token filter dans elasticsearch

Le principe est identique que dans Solr. Il y a bien une factory mais elle est différente de celle de Solr car elle reçoit les paramètres sous une autre forme. De plus, comme toutes extensions de elasticsearch, un token filter est ce que l’on appelle un plugin (https://www.elastic.co/guide/en/elasticsearch/plugins/5.1/intro.html). Il faut donc mettre en place ce plugin. Dans notre cas, le plugin fournit une factory qui elle même va créer le token filter. Pour terminer, on a besoin d’un assembly qui va décrire comment packager le plugin (les classes, les dépendances, la définition du plugin) pour pouvoir l’installer dans elasticsearch.

Pour elasticsearch, on a donc :

  • un plugin (une classe java) et son fichier de définition
  • une configuration de l’analyzer pour l’index de travail
  • une factory
  • le token filter
  • un assembly qui va décrire comment packager le plugin (les classes, les dépendances, la définition du plugin)

Le plugin : AnalysisAutoPhrasingPlugin.java

Il s’agit d’une classe très simple dans le cadre d’un token filter mais qui dépend du type de plugin.

Le fichier de définition du plugin : plugin-descriptor.properties

Il décrit le plugin : nom, version de elasticsearch compatible et nom de la classe du plugin.

La définition de l’analyzer dans l’index de travail

On crée un index avec un analyzer utilisant le token filter et indiquant quels sont les paramètres.

La factory : AutoPhrasingTokenFilter

Si on compare la factory elasticsearch à la factory Solr, on constate que la principale différence est dans les paramètres d’appel du constructeur et la manipulation de ces paramètres.

Le token filter Lucene

Ce toke filter est exactement le même que celui de Solr

L’assembly : plugin.xml

L’assembly permet à Maven de savoir quoi assembler dans la package du plugin (jar du plugin et des dépendances, fichier de description du plugin).

Structure du projet Maven et organisation des fichiers sources

Pour un Token filter devant fonctionner à la fois sous Solr et elasticsearch, il y a donc 3 composants et donc 3 modules Maven dans un projet père: le token filter Lucene, la factory pour Solr et la factory pour elasticsearch. La copie d’écran ci-dessous illustre cette organisation en un projet Maven constitué de 3 modules avec une arborescence hiérarchique et les 4 fichiers pom.xml.

Structure du projet Maven

Structure du projet Maven

Le projet principal : solr-es-auto-phrase-tokenfilter

Il est uniquement constitué du fichier pom.xml qui référence les 3 modules et définit les versions des librairies utilisées par les modules.

Le projet token filter Lucene : lucene-auto-phrase-tokenfilter

Dans le cas de ce filtre, il est constitué de la seule classe nécessaire au filtre et également de sa classe de tests.

Le module Maven pour le token filter Lucene

Le module Maven pour le token filter Lucene

Le fichier pom.xml est simple avec principalement la définition des dépendances.

Le projet token filter Solr: solr-auto-phrase-tokenfilter

Il est également constitué de la seule classe nécessaire à la factory et de sa classe de tests.

Le module Maven pour le token filter factory Solr

Le module Maven pour le token filter factory Solr

Le fichier pom.xml est simple également avec principalement la définition des dépendances. On remarque la dépendance avec le token filter Lucene.

Le projet token filter elasticsearch: es-auto-phrase-tokenfilter

Sa structure est plus complexe que pour Solr car outre la classe de la factory, il est constitué de la classe du plugin, du fichier de description du plugin et du fichier de description de l’assembly.

Le module Maven pour le plugin elasticsearch

Le module Maven pour le plugin elasticsearch

Le fichier pom.xml et plus complexe avec notamment le plugin Maven de construction de l’assembly “maven-assembly-plugin” et des règles d’exclusion dans les dépendances du fait de la grande sensibilité d’elasticsearch au conflits de librairies “Jar Hell” (https://dzone.com/articles/jar-hell-made-easy). On remarque également la dépendance avec le token filter Lucene.

Le résultat du build du projet est comme pour le le token filter Lucene et la factory Solr un fichier jar qui contient les différentes classe et le fichier de description du plugin, mais également l’assemblage sous la forme d’un fichier zip qui sera déployé dans elasticsearch : le plugin !

Résultat de la compilation du plugin

Résultat de la compilation du plugin

Le contenu de l’assemblage (es-auto-phrase-tokenfilter-0.0.1-SNAPSHOT.zip).

Le contenu du plugin elasticsearch

Le contenu du plugin elasticsearch

On y retrouve tout ce qui est nécessaire au fonctionnement du plugin et qui sera déployé dans le répertoire plugins de elasticsearch au moyen de la commande “elasticsearch-plugin”.

Le plugin déployé dans elasticsearch

Le plugin déployé dans elasticsearch

 

Dans cet article, j’ai décrit le principe de fonctionnement d’un plugin de type token filer dans elasticsearch ainsi qu’une organisation modulaire d’un projet eclipse afin de générer un token filter à destination à la fois de Lucene, de Solr et de elasticsearch.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *