zestedesavoir / zds-site

Cœur du projet technique de Zeste de Savoir
https://zestedesavoir.com
Other
268 stars 161 forks source link

Comment améliorer la recherche ? #4098

Closed pierre-24 closed 1 month ago

pierre-24 commented 7 years ago

Zoyeux nowel les gens !

Puisque c'est enfin noël, donc enfin les vacances, j'ai (enfin) du temps pour m'attaquer à un truc que je garde en tête depuis deux mois : la recherche (voir #4096). En effet, @Spacefox a déjà dit plusieurs fois qu'il vaudrait mieux passer à Elasticsearch (ES), plus puissant (ou en fait plus exploitable, puisque dessous, c'est Lucene à chaque fois) que ce que ZdS utilise actuellement. Bref, une meilleure recherche et un retour de la barre de recherche en barre d’accueil. D'ailleurs, je cite le renard :

[...] Ensuite, contrairement à aujourd'hui où on renvoie tous les résultats en vrac, il faudrait catégoriser les résultats (contenus rédigés d'abord, forums ensuite) et les champs de recherche (terme trouvé dans le titre prioritaire sur le terme trouvé dans le corps de texte, avec un système de poids – de mémoire c'est assez simple à faire).

Sauf que pour ça, il va falloir répondre à la question "qu'est ce qu'on attend comme résultat d'une recherche".

Quelques éléments avant de continuer

En préambule, il est important de savoir que ES classe ces données en documents, qui correspondent grosso modo à une ligne de BDD (on est dans un contexte NoSQL), donc un post, un topic (qui sont différents types de document), etc.

Scoring et boosting

Avant toute chose, il est bon de comprendre comment ES classe les résultats suite à une recherche. Si on effectue la recherche d'un terme dans l'ensemble des documents, ceux-ci sont classés par score, que ES calcule comme étant le produit TF * IDF, où la partie TF (term frequencies) est le nombre de fois qu'un terme apparait dans un document et IDF (inverse document frequencies) est l'importance du terme dans l'ensemble des documents.

Évidement, l'histoire ne s'arrête pas là, puisqu'on peut modifier le score par différents moyens, qui relèvent du boost:

Actuellement, je n'ai aucune idée de l'ordre de grandeur du facteur de boost, si c'est 2, 5, 10 ou 100, j'ai pas encore eu assez de données pour tester. Dans l'absolu, il faudra ajuster ça empiriquement.

tokenizer(s) et analyzer(s)

Afin d'effectuer ces recherches, le mieux est de ne pas faire des recherches fulltext (passer tout le texte en revue) mais de ne rechercher que certains termes. Par ailleurs, il est toujours mieux d'éviter d'avoir à ce casser la tête avec les problèmes de singulier/pluriel (par défaut "table" et "tables" ne sont pas les mêmes mots).

Du coup, chaque champ indexé passe par un analyzer, découpé en trois étapes :

Entrée → character filter → tokenizer → token filter → sortie

Et de manière générale, y'a moyen d'expliquer à ES que nous, on cause français, donc c'est plutôt pas mal.

Ici, je propose très clairement d'utiliser un analyzer qui comprend le français (donc qui vire les déterminants et met les mots au singulier), qui vire le HTML, qui passe tout en minuscule et qui remappe tout en ascii standard. Si vous voyez d'autres token filter intéressants, dites le moi.

Et alors ?

Bon, je me répette, le but du jeu, c'est d'avoir la recherche la plus performante possible. Évidement, y'a pas de réponse unique, même Google n'a pas encore trouvé ;)

Quoi ?

Premièrement, il faut se mettre d'accord sur ce qu'on on indexe. Actuellement, il s'agit de

À noter qu'à différents moments, on a également proposé d'indexer les utilisateurs. En soit, c'est pas difficile, mais à part le nom (et éventuellement la biographie), je vois pas trop quoi indexer.

Je propose éventuellement de booster les contenus sur les résultats issus du forum, mais tout dépend ce qu'on cherche à récupérer de la recherche. Je propose également de booster les topics par rapport aux messages et les contenus par rapport à ce qu'ils contiennent. La logiquue étant que si le terme recherché est dans le titre (du topic ou du contenu), il y a beaucoup de chance que la discussion porte dessus.

Comment ?

Deuxièmement, il faut définir ce qu'on indexe pour chacun des modèles (et comment on les boostent, éventuellement). Et troisièmement, il faut définir ce qui affecte les résultats.

Voici une petite proposition (notez que comme j'ai dit, je n'ai aucune idée de la valeur du facteur de boost, je place juste un ordre d'importance).

Topic

Champ Indexation Boost
Titre Oui 2.0
Sous-titre Oui 1.5
Forum Oui ---
Auteur Non ---
Dernier message Non ---
Est résolu éventuellement 1.0
Est verrouillé éventuellement 1.0
Est en post-it éventuellement 1.0
Tags du forum Oui 3.0

Post

Champ Indexation Boost
Auteur Non ---
Editeur Non ---
Adresse IP de l'auteur Non ---
Position éventuellement 1.0
Texte Non ---
Texte en Html Oui 2.0
Likes éventuellement 1.0
Dislikes éventuellement 1.0
Date de publication éventuellement 1.0
Date d'édition Non ---
Est visible Oui 1.0
Texte de masquage Non --
Est utile éventuellement

Contenus

(en fait les contenus publiés)

Champ Indexation Boost
Type de contenu éventuellement 1.0
Slug du contenu publié Non ---
Pk du contenu publié Non ---
Date de publication éventuellement ---
Date de mise à jour éventuellement ---
Auteurs Non ----
Tailles des fichiers téléchargeables Non ---

(... et de la partie non publiée)

Champ Indexation Boost
Titre Oui 2.0
Description Oui 1.5
Old pk Non ---
Sous-Catégorie Oui 3.0
Tags du contenu Oui 3.0
Image du tutoriel Non ---
Galerie d'images Non ---
Sujet beta associé Non ---
Licence Non ---
Aides Non ---
Chemin relatif images Non ---
Derniere note Non ---
Est verrouillé Non ---
Support du Javascript Non ---

Extraits et conteneurs

Tout d'abord, je propose de ne pas indexer tout les conteneurs et ne pas indexer les extraits tels quels, mais seulement la forme qu'ils ont quand ils sont publiées, soit tout les extraits d'un même chapitre rassemblés.

Cette proposition est assez forte, mais possède selon moi plusieurs avantages:

Mais évidement, ça se discute.

Et du coup,

Champ Indexation Boost
Titre Oui 2.0
slug Non ---
introduction Non ---
conclusion Non ---
parent Non ---
Position dans le parent Non ---
Enfants Non ---
Contenu Oui 1.0

Et donc ?

Si on suis ce que je viens de dire, ce qu'on obtient est une recherche qui sort en priorité les contenus sur les forums, qui donne la priorité aux tags et au titre envers les différents champs de texte et qui discrimine éventuellement selon différents critères plus ou moins objectifs (date de publication, position, ...).

C'est un peu ma vision de ce que la recherche devrait donner, mais c'est ma vision, donc n'hésitez pas à argumenter.

Bon amusement ;)

artragis commented 7 years ago

Bonjour,

Pour revenir sur la différence boost solr/boost elastic search : le boost solr est forcément normalisé, et la somme des boosts d'un document est égale à 1 (du moins c'est ce que disait la documentation haystack), sur elastic search, tu peux clairement booster plus librement, et quand il y a de la liberté, je suis un fan de la suite de fibonacci. (1, 2, 3, 5, 8, 13, 21... mais je pense que déjà 13 c'est énorme)

Je pense clairement qu'il faut booster les posts en fonction des +/-1. Il ne sert pas de les booster en mode stéroïde mais au moins la pertinence sera accrue.

Sinon je vois que tu as mis un "éventuellement" à "est utile". Je pense qu'il faut clairement indexer ça quitte à booster légèrement.

Autre chose qui m'a clairement choqué : tu n'indexe pas la licence. Pour moi on doit --dans le futur-- donner la possibilité aux gens qui le veulent, surtout si le nombre de contenus augmente toujours, la possibilité de filtrer en fonction des licences. Le libre c'est aussi ça.

Pour l'idée de réduire la granularité de stockage, tu reviens aux origines de la zep-12 qu'on avait dû abandonner à cause de haystack, donc je te soutiens totalement.

pierre-24 commented 7 years ago

Je pense clairement qu'il faut booster les posts en fonction des +/-1. Il ne sert pas de les booster en mode stéroïde mais au moins la pertinence sera accrue.

Je suis d'accord, mais j'ai peur de faire ressortir les trolls, qui se mangent plein de pouces verts ;)

Sinon je vois que tu as mis un "éventuellement" à "est utile". Je pense qu'il faut clairement indexer ça quitte à booster légèrement.

Chui d'accord :)

Autre chose qui m'a clairement choqué : tu n'indexe pas la licence. Pour moi on doit --dans le futur-- donner la possibilité aux gens qui le veulent, surtout si le nombre de contenus augmente toujours, la possibilité de filtrer en fonction des licences. Le libre c'est aussi ça.

Oui. Après, y'a deux solution : soit j'indexe uniquement ce qui est actuellement nécessaire (j'ai besoin d'un petit peu plus que ce que j'ai présenté, en pratique, pour l'affichage), soit j'indexe tout les champs potentiels en disant "ça servira bien un jour". Faut voir ce que ça nous coute en terme de stockage et de réactivité :)

Pour l'idée de réduire la granularité de stockage, tu reviens aux origines de la zep-12 qu'on avait dû abandonner à cause de haystack, donc je te soutiens totalement.

Me souvenais plus qu'on aie dit ça, mais ça doit être pour ça que ça ressort instinctivement aujourd'hui :)

Après, en pratique, je sais pas encore exactement comment je vais indexer ça convenablement. J'ai 2 pistes, on verra ce que ça va donner :)

artragis commented 7 years ago

Me souvenais plus qu'on aie dit ça, mais ça doit être pour ça que ça ressort instinctivement aujourd'hui :)

bah en fait au départ on avait dit qu'on ferait tout pivoter sur le html généré pour un chapitre. Mais quand on est arrivé à la recherche on s'est rendu compte que haystack n'aimait pas trop alors on a demandé de l'aide à Hugo.

Je pense qu'il faut faire confiance à elasticsearch : indexer en français à partir d'un texte html, le truc sait très bien le faire.

Situphen commented 7 years ago

Cette idée est super chouette !

Les topics verouillés sont dévallués (à discuter, puisque tout les sujets de bêta finissent verouillés) ;

Les sujets de la bêta finissent verrouillés quand ils vont en validation et/ou qu'ils sont publiés non ? Donc personnellement je n'en tiendrait pas compte et je resterais sur du "les topics verrouillés sont dévalués" :)

pierre-24 commented 7 years ago

Disons que je suis très prudent et que je demande au gens de vérifier que j'ai pas oublié quelque chose :)

DevHugo commented 7 years ago

Je suis désolé, j'était partis en vacances et du coup, j'arrive un peu après la bataille !

Je pense qu'il faut faire confiance à elasticsearch : indexer en français à partir d'un texte html, le truc sait > très bien le faire.

Pour solr, j'avais pas trouvé de tokenizer, token filter ou autre qui vire toutes les balises HTML ! Du coup, je le faisait à la main. Si tu as trouvé comment faire mieux, bravo a toi !

Ne pas prendre ce message comme un souhait de truc à implémenter de suite, la PR en cours est très bien comme elle est, on pourrait améliorer avec le temps. C'est plus la liste de noël (comment ça noël est déjà passé ?) ^^

Je pense que c'est déjà un énorme pas, mais que la discussion n'a pas porté sur un point pour moi qui est aussi important que la pertinence des algos du moteur de recherche, les critères de recherche et même peut-être qui serais encore mieux, les facets.

Pour moi, tu va arriver rapidement à la limite de ce que tu peux faire pour aider le moteur de recherche à fournir des résultats pertinent. Il va falloir jouer sur plusieurs autres tableaux.

Facet

Spacefox, à l'époque avait fournit une liste de facet:

Tutoriels, articles, tribunes publiés

  • Tags hiérarchiques (facette)
  • Titre
  • Sous-titre
  • Date de publication (facette)
  • Date de dernière mise à jour (facette)
  • Auteurs (facette)
  • Contenu intégral (toutes les intros, toutes les conclusions, toutes les parties)

Sujets de forums

  • Tags hiérarchiques (facette)
  • Titre
  • Sous-titre
  • Date de publication (facette)
  • Date du dernier post (facette)
  • Auteur (facette)
  • Groupe d'appartenance (public ou non)
  • Contenu du premier message

Messages de forums

  • Sujet
  • Auteur (facette)
  • Date de publication (facette)
  • Groupe d'appartenance (public ou non)
  • Contenu du message Source

ElasticSearch fait ça de base, faut juste attaquer la bonne adresse. Avec Solr, c'était assez simple, je suppose qu'avec ElasticSearch ça doit être aussi facile.

Tu peux ajouter des critères de recherche comme « Est résolu », « Est en post-it », « Est verrouillé ».

Sur le moteur de recherche

Pour les topics, tu as mit que tu voulais indexer les forums. Je suis complètement d'accord qu'il va falloir enregistrer la donnée pour pouvoir après afficher le bon forum selon les droits correspondant aux utilisateurs. Mais je suis pas sur que l'indexer directement sans jouer sur son boosting soit une bonne idée. Si l'utilisateur tape dans la recherche un mot clé contenant le nom d'un forum, il va se retrouver avec tous les sujets du forum. Ça va si les contenus sont boostés suffisamment pour apparaître en premier mais sinon les résultats pertinents vont être fondu dans la masse. Pour les deux boost : Je pense que c'est une très bonne idée de booster les 2 attributs Est résolu, Est en post-it. Mais je vois ça plus comme des critères de recherche.

Tu es sur que tu dois indexer ce type de champ ? j'aurais juste sauvegardé son contenu sans l'indexer.

pierre-24 commented 7 years ago

Grosso modo, je suis d'accord avec ce que tu dis sur les facets, à terme ce serait beaucoup plus gérable de les utiliser. Et oui, c'est facile avec ES ;)

Pour les topics, tu as mit que tu voulais indexer les forums. Je suis complètement d'accord qu'il va falloir enregistrer la donnée pour pouvoir après afficher le bon forum selon les droits correspondant aux utilisateurs. Mais je suis pas sur que l'indexer directement sans jouer sur son boosting soit une bonne idée. Si l'utilisateur tape dans la recherche un mot clé contenant le nom d'un forum, il va se retrouver avec tous les sujets du forum. Ça va si les contenus sont boostés suffisamment pour apparaître en premier mais sinon les résultats pertinents vont être fondu dans la masse.

Je crois que j'ai fourché sur indexé. En effet, dans la version finale, le forum est sauvegardé, mais la recherche n'as pas lieu sur ce champ. Donc ça rejoint ce que tu dis :-)

Pour les deux boost : Je pense que c'est une très bonne idée de booster les 2 attributs Est résolu, Est en post-it. Mais je vois ça plus comme des critères de recherche.

Voir point précédent.

DevHugo commented 7 years ago

Juste pour garder en mémoire.

A-312 commented 6 years ago

et : https://zestedesavoir.com/forums/sujet/9037/fonctionnement-du-moteur-de-recherche-de-zds/

philippemilink commented 1 month ago

Je propose de clore ce ticket pour les raisons suivantes :

N'hésitez pas à ouvrir un autre ticket pour signaler un bug ou proposer une évolution, ou un sujet sur le forum si vous voulez discuter de la recherche !