Lucene - ignorer les accents lors de l'indexation et la recherche | ignore diacritics
Lucene.net est un moteur de recherche écrit en C#, il s'agit du portage du projet lucene écrit en Java. Ce moteur est très rapide, simple à mettre en place et gratuit, parmi les sites qui l'utilisent on peut noter le site wikipedia.
Lorsque vous créez un index ou une requête de recherche, vous avez besoin d'un analyseur. Cet analyseur va, entre autres, effectuer des traitements sur les mots. Par exemple, si vous recherchez le mot clé "Ecrans", l'analyseur pourra convertir ce mot en "ecran". Ainsi vous obtiendrez des résultats comportant le mot "Ecran" (avec une majuscule) ou "ecrans" (au pluriel) lorsque vous rechercherez "ecran".
Il existe plusieurs Analyseur natif dans Lucene, ce post n'a pas pour objectif de détailler les différents analyseur ainsi que leur fonctionnement, je vous invite à consulter cet article : Lucene.Net - Text Analysis si vous souhaitez plus d'information.
Il existe d'autres analyseur plus complexe, le plus utilisé est certainement SnowBall qui permet de supprimer le pluriel des mots, les conjugaisons, etc ... ou alors les mots bruyants/inutiles comme "le", "avec", ...
Si vous utilisez Lucene vous avez tout interêt à utiliser cet analyseur.
Bien que très pratique, SnowBall ne permet pas de supprimer les accents des mots (aussi appelé signe diacritique), ainsi "écran" est différent de "ecran".
Voici un bout de code illustrant ce problème :
static void Main(string[] args)
{
// Creation de l'index en memoire
Directory directory = new RAMDirectory();
// Creation de l'analyseur pour des mots en francais
Analyzer analyzer = new SnowballAnalyzer("French");
IndexWriter writer = new IndexWriter(directory, analyzer);
Document doc;
// ajout des documents dans l'index
doc = new Document();
doc.Add(new Field("ID", "1", Field.Store.YES, Field.Index.NO));
doc.Add(new Field("Content", "ecran", Field.Store.NO, Field.Index.TOKENIZED));
writer.AddDocument(doc);
doc = new Document();
doc.Add(new Field("ID", "2", Field.Store.YES, Field.Index.NO));
doc.Add(new Field("Content", "écran", Field.Store.NO, Field.Index.TOKENIZED));
writer.AddDocument(doc);
// fermeture de l'index
writer.Optimize();
writer.Close();
// creation de la requete de recherche
QueryParser parser = new QueryParser("Content", analyzer);
Query query = parser.Parse("ecran");
// Recherche
Searcher searcher = new IndexSearcher(directory);
Hits hits = searcher.Search(query);
Console.WriteLine(hits.Length()); // affiche 1
}
Pour ignorer les accents et faire en sorte que "écran" = "ecran", nous devons faire notre propre Analyzer.
Pour cela nous allons hériter de la classe SnowballAnalyzer, surcharger la méthode TokenStream et utiliser le filtre ISOLatin1AccentFilter qui permet de supprimer les accents.
class MyAnalyzer : SnowballAnalyzer
{
public MyAnalyzer(String language)
: base(language)
{ }
public override TokenStream TokenStream(string fieldName, TextReader reader)
{
TokenStream result = base.TokenStream(fieldName, reader);
result = new ISOLatin1AccentFilter(result);
return result;
}
}
Ensuite, il vous suffit d'utiliser la classe MyAnalyzer au lieu de SnowballAnalyzer afin de ne plus prendre en considération les accents lors de l'indexation et de la recherche.
Si vous regardez le code de la classe ISOLatin1AccentFilter, vous noterez qu'elle ne fait pas que supprimer les accents (diacritics), mais aussi les ligatures ainsi cœur = cœur.
D'autres astuces au niveau des analyseurs Lucene ?