Skip to content

Elasticsearch

Indexation

  • Pour lancer une indexation complète, aller en front dans le BO (/adminspace/elasticsearch) puis encart Réindexation > Forcer la réindexation
  • La réindexation prend qq secondes pour pistes et articles mais plusieurs minutes pour les ~20k éclaireurs

Structure de données

  • Plutôt que d'indexer TOUS les champs des entités Articles, Pistes ou Users (éclaireurs), on aplatit dans un objet simplifié comportant uniquement les champs utiles à la recherche
  • Les 3 entités sont dans le même index et partagent des champs en commun : id (de l'entité sql), name,createdAt, updatedAt, type (article|piste|eclaireur). Les pistes et articles partagent qq champs
  • Lors d'une requête, on va d'abord récupérer les types+ids via Elastic, mais on ne retournera jamais les docs ES à l'utilisateur : on va relancer une requête SQL sur ces ids (généralement un subset de 50 items max) et réhydrater les objets. Objectifs :
  • unifier le format des objets renvoyés par l'API (typage des objets et sous-objets)
  • minimiser les changements de structure de l'index ES lorsque les entités s'enrichissent
  • unifier les composants front en termes d'affichage

Environnement

  • Le même serveur ES accueille les index inspire-staging et inspire-prod : https://inspire-elasticsearch.a1.admantic.eu
  • Cluster avec 3 nodes, en LB derrière un Nginx (config gérée par Admantic)
  • Le cluster est protégé par Basic Auth (⚠️ crucial car ES ne fournit aucune sécurité native ni en lecture ni en écriture)

Pourquoi avoir choisi Elasticsearch ?

  1. recherche plein texte multi-champs avec stemming/stopwords/folding/elision sur les articles/pistes : ex. "les Biologistes" -> "biolog*" -> renvoie les résultats type "études de biologie"

  2. ranking : le scoring de pertinence multiplicatif (plus l'article contient de mots de la requête, plus il remonte), la pondération par field (ex. titre * 2) et les critères de pondération cumulatifs (pertinence + date de création en décroissance Gaussienne + présence de tags multiplicatifs). Out of the box, on a une bien meilleure pertinence de base qu'avec un SQL.

  3. performance : sur des requêtes plein texte avec des sous-objets (ex. user.parcoursEclaireurs.piste) on reste sur des requêtes < 50ms vs > 500ms en PostGreSQL, avec une charge serveur réduite

  4. matching (pas encore implémenté en avril 26): trouver des éclaireurs selon le profil du LY -> on alimente une requête ES avec pondération sur les critères pertinents (à définir avec les PM): pistes d'études, zone géographique, genre?, booléens type stage/alternance/bourse, + randomisation

Limites connues et évolutions possibles

  • Alias d'index : pour éviter le downtime lors d'une réindexation complète, utiliser des alias :
  • l'index inspire-prod est conservé, mais on lui crée l'alias inspire-prod-alias et on fait pointer la prod vers cet alias
  • lors d'une réindexation, on crée un nouvel index (ex. inspire-prod-202602040903), on le remplit, puis on lui attribue l'alias inspire-prod-alias
  • une fois que ça tourne, on peut effacer l'ancien alias inspire-prod-alias

  • Index dev à supprimer : il y a un index inspire-dev sur le serveur, pratique pour des tests mais autant avoir une instance docker locale et éviter de disséminer les codes dans les env de dev

  • Séparer les index (à débattre) : le choix de regrouper les 3 entités article, piste et eclaireur, initialement pour une recherche unifiée, pourrait être rediscuté si les recherches restent séparées comme actuellement (avril 26). On aurait une structure plus claire avec des index inspire-articles-prod, inspire-pistes-prod, inspire-eclaireurs-prod.