SPIP-Contrib

SPIP-Contrib

عربي | Deutsch | English | Español | français | italiano | Nederlands

286 Plugins, 197 contribs sur SPIP-Zone, 325 visiteurs en ce moment

Accueil > Navigation > Recherche > Nouveau Critére : trouver les articles (ou autre) similaires

Nouveau Critére : trouver les articles (ou autre) similaires

31 juillet 2005 – par mortimer

Toutes les versions de cet article : [Español] [français]

3 votes

Attention, cette contribution est EN CHANTIER : elle n’est peut-être pas fonctionnelle.

Trouver des articles avec un texte similaire en utilisant le moteur d’indexation et la déclaration d’un nouveau critère de boucle.

Nota SPIP-Contrib : le système d’indexation à évolué à partir de SPIP 1.9, donc cette contrib n’est probablement pas utilisable en l’état. Elles est cependant conservée comme base potentielle d’une évolution ... un plugin ?

Idée

SPIP stocke dans les table index_* des informations sur l’indexation des articles. Pour l’instant, ces tables ne sont utilisées que pour calculer les résultats d’une recherche.

Leur structure est simple :
-  il y a une table dictionnaire centrale, qui liste tous les mots importants rencontrés sur le site,
-  pour chaque type d’objet il y a une table qui lie les ID avec les mots qui se trouvent dans cet objet. Ce lien est pondéré avec un nombre de points (qui correspond à l’importance du mot dans le texte).

Au lieu de faire une recherche en partant d’un mot comme le fait actuellement le critère {recherche}, on aimerait trouver les articles semblables à un autre (en comptant le nombre de mot qu’ils partagent).

Il existe une mesure simple pour faire cela : On peut voire deux documents comme des vecteurs de N dimensions, chacune correspondant à un mot dans le dictionnaire. Les valeurs stockées dans le vecteur d’un document représentent le poids de chaque dimension (chaque mot) dans ce document.

Par exemple :

dico doc1 doc2
petit 0 3
wiki 10 3
spip 3 10
chemin 4 0

Une mesure de la similarité entre les deux documents est le produit vectoriel entre les deux vecteurs :

S = 0*3+10*3+3*10+4*0 = 60

Croyez moi (ou corrigez moi), mais cela correspond à une requête sur les tables d’index de SPIP :

SELECT
           primaire.id_article,
           secondaire.id_article,
           SUM(primaire.points*secondaire.points) AS similarite
FROM
        spip_index_articles AS primaire,
        spip_index_articles AS secondaire
WHERE
          primaire.hash = secondaire.hash AND
          primaire.id_article = 2
GROUP BY secondaire.id_article

Critère

On va donc implémenter un nouveau critère [1] : {similaire} pour les boucles :

-  On ajoute un nouveau champ dans le select. Il s’agit du calcul du produit scalaire entre les deux vecteurs, il faut noter que l’ordre sera du moins similaire au plus, il faudra donc plutôt utiliser ce critère avec {inverse}.

-  On ajoute trois nouvelle table sur lesquelles faire la jointure :

  • 2 tables index_TYPE, pour comparer l’objet actuel avec tous les autres indexés,

On peut déjà remarqué que l’on utilise la variable id_table pour connaître le type de l’objet pris en compte dans la boucle

-  on ajoute quatre clause WHERE :

  • la table primaire contraints à l’objet considéré. On récupère son ID grâce à la fonction calculer_argument_precedent,
  • on prend tous les autres objet ayant les mêmes mots dedans (on vérifie avec le hash du mot),
  • la dernière contrainte met en rapport la liste d’article similaire avec la table de l’objet principal (celle ci utilise $boucle->id_table.'.'.$boucle->primary comme index),

-  on groupe la colonne secondaire pour ne pas avoir les objets similaire en double (c’est à ce moment que le produit scalaire est calculé),

Balise

Le nouveau compilateur de spip permet aussi d’ajouter ses propres balises. Ici on veut pouvoir récupérer la nouvelle colonne calculé par notre requête : la « similarité ».

Voici le code, il s’agit du même code que la boucle POINTS qu’offre une boucle recherche :

On peut utiliser ce critère dans n’importe quelle boucle à l’intérieur d’une boucle ayant le critère {similaire}. On va donc recherche dans les boucles englobantes la première qui utilise ce critère.

On peut ensuite récupérer la valeur de cette colonne dans la pile fournie par le compilateur.

Tout cela est fait automatiquement par la fonction rindex_pile.

Boucle Exemple

Une boucle très simple peut être utilisée pour utiliser ce critère sur les articles :

On peut aussi dire à SPIP de trier par un champ calculé dans une requête [2]. Ainsi, on trie par similarité puis on inverse, pour avoir les articles triés dans un ordre décroissant de similarité.

Ce critère va retourner tous les articles ayant au moins un mots en commun avec celui en cours, ce qui peut faire beaucoup. On limite donc la boucle à 5 résultats.

Optimisation

Pour ceux qui s’y connaissent en SQL et on une petite idée de la taille des tables d’index, le besoin d’optimisation est évident. Pour les autres, je vais expliquer un peu.

La requète SQL faite par ce critère fait trois jointures [3] sur de très grosses tables. Par exemple pour une boucle article :
-  la table articles contient tous les articles,
-  la table index_articles contient une ligne par mot indexé, par article. Cela veut dire que si l’article X a 10 mots indexé, il y a aura 10 lignes dans la table. Imaginez la taille de cette table si il y a beaucoup de longs articles.

Ainsi, il faut absolument éviter de faire toutes ces jointures. Malheureusement, la jointure de index_quelquechose sur elle même est obligatoire. Par contre, la jointure sur la table quelquechose n’est pas obligatoire.

Effectivement, elle est obligatoire si on veut appliquer ce critère directement sur la table articles. C’est plus intuitif et permet de récupérer directement les informations sur l’article.

Ici, on va exposer une méthode qui évite cette jointure sur la table article. Ce nouveau critère s’appliquera directement sur une table index_quelquechose et permettra de récupérer les IDs des articles
similaires.

Il faut d’abord dire à SPIP qu’on peut boucler sur les tables index en lui décrivant les colonnes disponibles :

il faut aussi déclarer les fonctions boucle_... pour initialiser la requette sur ces tables :

On déclare ainsi quelle est la table principale sur laquelle on fait les requettes pour chacune de ces boucles.

On peut maintenant déclarer le critère :

Le principe du critère est le même qu’avant, sauf que SPIP va directement faire le SELECT initial depuis une table index_quelquechose. On a donc juste à ajouter la jointure sur cette table et les critères en conséquence.

Malheureusement, on ne peut pas directement utiliser #ID_ARTICLE à l’intérieur de la boucle sur index_quelquechose. Il nous faut donc ajouter une balise pour récupérer l’id qui nous intéresse :

La boucle à faire est donc un peu plus complexe. Par exemple pour les articles :
-  on doit imbriquer une boucle articles dans la boucle index_articles,
-  on doit dire à cette boucle de sélectionner l’article ayant le même id que #ID_SIMILAIRE : {id_article=#ID_SIMILAIRE}
-  on peut exclure l’article en cours avec le critère {exclus}
-  comme le critère {exclus} est sur la boucle intérieur, on est obligé de limiter plus largement la boucle externe : {0,7} au lieu de {0,5}.

P.-S.

Notez bien que ce critère peut être utilisé sur tous les types de boucles avec lesquels on peut utiliser le critère {recherche}. En fait, on peut trouver les éléments similaire de tout objet qui est indexé par SPIP, il faut que la table index relative soit bien déclarée comme nouvelle table comme indiqué dans cet article.

Notes

[1Le code proposé ici peut se placer dans mes_fonctions.php3.

[2non déclaré comme colonne à SPIP.

[3Il colle les tables les unes aux autres en faisant toutes les combinaisons possibles.

Dernière modification de cette page le 4 octobre 2011

Retour en haut de la page

Répondre à cet article

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici Les choses à faire avant de poser une question (Prolégomènes aux rapports de bugs. )
Ajouter un document

Retour en haut de la page

Ça discute par ici

  • Mailsubscribers

    16 janvier 2013 – 274 commentaires

    Ce plugin permet de gérer les inscriptions (ou abonnements) à la diffusion de contenu par email. Mailsubscribers permet de gérer les inscriptions par Opt-in simple ou double et la désinscription par URL. Ce plugin gère également plusieurs listes (...)

  • noiZetier v2

    9 novembre 2012 – 36 commentaires

    Le noiZetier offre une interface d’administration permettant d’insérer au choix des éléments modulaires de squelettes (noisettes) et de les ajouter ainsi à ses squelettes. Compatibilité La version 2 du noizetier fonctionne sous SPIP 3. Elle est (...)

  • cirr : plugin « rédacteur restreint »

    29 octobre 2010 – 60 commentaires

    Ce plugin « cirr : rédacteur restreint » permet d’affecter des rubriques aux rédacteurs et modifie les droits afin qu’un rédacteur restreint (ou un administrateur restreint) voit dans l’espace privé uniquement les rubriques qui lui sont affectées (et leur (...)

  • Un retour d’expérience d’utilisation de Formidable

    26 octobre – commentaires

    Il s’agissait de créer un formulaire d’inscription à un évènement modérer les inscriptions dans le privé publier les inscriptions dans le public Nous avons discuté de cette présentation lors de l’apéro SPIP du 15 février 2016 à la Cantine (...)

  • Métas +

    3 décembre – 14 commentaires

    Améliorez l’indexation de vos articles dans les moteurs et leur affichage sur les réseaux sociaux grâce aux métadonnées Dublin Core, Open Graph et Twitter Card. Installation Activer le plugin dans le menu dédié. Dans le panel de configuration, (...)

Ça spipe par là