Elasticsearch : une recherche full-text en français

· 6 min de lecture

Accents, pluriels, élisions et fautes de frappe : comment régler Elasticsearch pour bien chercher en français.

En bref

Un bon moteur de recherche doit trouver « développeur » quand on tape « développeurs », même avec une faute. L’article montre comment régler Elasticsearch pour qu’il comprenne bien le français.

Un mot technique vous échappe ? Le glossaire du développement web l’explique simplement.

Chercher « développeurs » doit trouver « développeur », « l’école » doit répondre à « ecole », et une faute de frappe ne devrait pas tout faire échouer. Un moteur de recherche full-text comme Elasticsearch sait faire tout cela, à condition de lui expliquer qu’il indexe du français.

Le rôle de l’analyzer

À l’indexation comme à la recherche, le texte passe par un analyzer qui le découpe en termes et les normalise. L’analyzer standard se contente de découper et de mettre en minuscules : « Développeurs » et « developpeur » restent deux termes différents, qui ne se trouvent pas.

Un analyzer pour le français

Elasticsearch fournit un analyzer french prêt à l’emploi. En le recréant soi-même, on peut y ajouter asciifolding, qui enlève les accents. Ces réglages se font à la création de l’index :

{
  "settings": {
    "analysis": {
      "filter": {
        "fr_elision": {
          "type": "elision",
          "articles_case": true,
          "articles": ["l", "m", "t", "qu", "n", "s", "j", "d", "c",
                       "jusqu", "quoiqu", "lorsqu", "puisqu"]
        },
        "fr_stop": { "type": "stop", "stopwords": "_french_" },
        "fr_stemmer": { "type": "stemmer", "language": "light_french" }
      },
      "analyzer": {
        "french_folded": {
          "tokenizer": "standard",
          "filter": ["fr_elision", "lowercase", "fr_stop",
                     "asciifolding", "fr_stemmer"]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "french_folded",
        "fields": { "raw": { "type": "keyword" } }
      }
    }
  }
}
  • elision retire les articles élidés : « l’école » devient « école ».
  • lowercase met tout en minuscules.
  • stop supprime les mots vides (« le », « de », « et ») qui n’apportent rien à la pertinence.
  • asciifolding retire les accents : « école » et « ecole » deviennent le même terme.
  • light_french ramène les mots à leur racine : « développeurs » et « développeur » se rejoignent.

Le sous-champ keyword (title.raw) conserve la valeur exacte pour les tris et les agrégations, qu’un champ text analysé ne permet pas.

Tolérer les fautes de frappe

{
  "query": {
    "bool": {
      "must": {
        "multi_match": {
          "query": "developeur angular",
          "fields": ["title^3", "skills^2", "description"],
          "fuzziness": "AUTO"
        }
      },
      "filter": { "term": { "available": true } }
    }
  }
}
  • fuzziness: "AUTO" accepte une ou deux lettres d’écart selon la longueur du mot.
  • Le suffixe ^3 donne plus de poids à une correspondance dans le titre.
  • Les critères exacts vont dans filter : ils ne comptent pas dans le score et peuvent être mis en cache.

Vérifier avec l’API _analyze

Quand un document ne remonte pas, l’API _analyze montre exactement les termes produits par un analyzer pour un texte donné. C’est le premier réflexe à avoir, avant de toucher aux requêtes :

{
  "analyzer": "french_folded",
  "text": "L’école des développeurs"
}

Une bonne recherche se joue surtout à l’indexation : une fois les termes correctement normalisés, les requêtes restent simples.