Carnet Wiki

Sphinx

SPIP-Contrib :: Carnet Wiki :: Recherche :

Sphinx

Sphinx est un logiciel libre pour l’indexation et la recherche, disponible à l’adresse http://sphinxsearch.com/

Le plugin sphinx permet à SPIP de communiquer avec ce moteur, pour afficher les pages de résultats.

ATTENTION PLUGIN OBSOLETE

Ce plugin est désormais remplacé par le plugin Indexer.

http://contrib.spip.net/Sphinx-Indexer

© Fil 2013, licence GNU/GPL.

Téléchargement

Le plugin est disponible via dans le dépôt et par SVN : svn co svn://zone.spip.org/spip-zone/_plugins_/sphinx/trunk/ plugins/sphinx/.

Le code est consultable ici : http://zone.spip.org/trac/spip-zone/browser/_plugins_/sphinx/trunk/.

Connexion

dans mes_options.php, on définira la source des données, et, si besoin, le serveur et le port :

define('_SPHINX_SOURCE', 'monsite');
define('_SPHINX_SERVER', 'localhost');
define('_SPHINX_PORT', 9312);

on peut aussi indiquer la taille des extraits (par défaut, 400 caractères) :
define('_SPHINX_COUPER_INTRO', 150);

Indexation

Ce document ne traite pas de l’installation de sphinx ; on suppose qu’il est installé et tourne correctement.

Pour le moment, le plugin ne s’occupe pas de mettre à jour à partir de SPIP les données indexées. Ce sera l’objet d’un futur développement, utilisant le module RT de sphinx. On est donc dans un schéma où la base est indexée directement par sphinx, qui va lire régulièrement (cron) les données dans la base SQL.

Vous trouverez dans le répertoire exemples/ (http://zone.spip.org/trac/spip-zone/browser/_plugins_/sphinx/trunk/exemples/ ), deux exemples de fichiers de configuration :
— articles.cf indexe les articles d’un site, avec leurs auteurs et leurs mots-clés, en indexant la date_redac à la place de date quand celle-ci est définie ;
— forum.cf indexe les forums d’un site, en les groupant par thread.

cron

Dans exemples/ figure aussi un fichier cron.php qui vérifie la date de modif et relance proprement l’indexation en cas de besoin ; ce script produit également, une fois par jour, une liste des 100 000 mots les plus courants dans la base, avec leur nombre d’occurences (fréquences), dans le fichier /var/local/sphinx/data/{index}.dict.txt.

Page de résultats

Un squelette de démonstration se trouve à l’adresse ?page=demo/recherche&recherche=xxxx.

Une boucle typique est de la forme :

<BOUCLE_articles(DATA){source sphinx,#ENV**,selection} {pagination 10}>
   <li><a href="#VALEUR{attrs/url}">[(#VALEUR{attrs/titre}|typo)]</a></li>
</BOUCLE_articles>

Dans cette boucle DATA, le critère {source sphinx,#ENV**,articles} appelle la fonction inc_sphinx_to_array_dist(), définie dans le fichier inc/sphinx.php, en lui passant l’environnement de la page (mots recherchés, pagination…), ainsi que le nom d’une sélection (ici selection).

Cette boucle DATA provoque une interrogation directe de sphinx, sans passer par le critère {recherche}. Elle est donc très rapide. Mais le plugin surcharge aussi le critère {recherche} classique, en prenant tous les résultats sphinx et en les intégrant, avec leur score, dans la table spip_resultats, exactement comme le fait le plugin Fulltext — et à condition d’avoir aussi activé ce dernier [1].


Options avancées

Avant la recherche :

Sphinx est extrêmement rapide, on va donc lui déléguer un maximum de travail ; si on veut par exemple appliquer un tri (par date, par pertinence) ou encore restreindre des résultats à un sous-ensemble d’articles, il est beaucoup plus efficace de signaler ces critères à sphinx, plutôt que de les ajouter dans la boucle DATA.

Exemple 1 : on veut faire une recherche restreinte aux articles ayant le mot-clé « cartographie » (id_mot=617), il suffit de créer, dans mes_fonctions.php :

function sphinx_selection_cartes(&$cl,&$sources,&$query) {
   # {attrs/type=617}
   $cl->SetFilter ( "type", array(617), $exclude=false );
}

et faire alors une boucle <BOUCLE_articles(DATA){source sphinx,#ENV**,cartes} ...>.

(La variable $exclude=true si l’on veut éliminer les articles ayant le mot-clé 617.)

Exemple 2 : notre site permet d’interroger une seconde base de données indexée par sphinx, par exemple un catalogue de films, dans l’index dvd :

function sphinx_selection_films(&$cl,&$sources,&$query) {
   $sources = 'dvd';
}

avec la boucle <BOUCLE_articles(DATA){source sphinx,#ENV**,films} ...>.

Après la recherche :

Si l’on veut filtrer ou enrichir les résultats donnés par sphinx, on peut encore appliquer un filtre après la requête. Une fois récupérée la liste des éléments trouvés par sphinx, le plugin le passe à la fonction sphinx_filtrer_resultats(), qui peut alors supprimer ou modifier certains résultats.

Exemple, pour un site ayant aussi un site de tests (mais exploitant la même base d’indexation sphinx) :

function sphinx_filtrer_resultats(&$r) {
   if ($_SERVER["HTTP_HOST"] == "alpha.monsitespip.tld") {
       foreach ($r as $k=>&$w) {
           $w['attrs']['url'] = str_replace('http://www.monsitespip.tld/', 'http://alpha.monsitespip.tld/', $w['attrs']['url']);
       }
   }
}

Options de langue

ligatures. Sphinx ne dispose pas d’une gestion propre des ligatures, ce qui fait qu’en cherchant boeuf on ne peut pas trouver bœuf ; un script, ligatures2wordforms.php (également disponible dans exemples/) permet de contourner ce problème en établissant la liste de tous les mots contenant une ligature, pour constituer un fichier wordforms.txt que sphinx pourra ensuite utiliser comme liste de « synonymes ». Le réglage à ajouter dans la configuration de l’indexation est le suivant :

wordforms = /chemin/vers/wordforms.txt

C’est assez chatouilleux : dès que ce fichier est modifié, il faut tout réindexer, et relancer le serveur.

A noter, pour le moment seule la ligature Œ = OE est gérée.

lemmatisation, stemmatisation. Là c’est #TODO, je n’ai pas encore réussi à le faire fonctionner.

Racines. enable_star permet d’autoriser la recherche sur le début d’un mot ; cela exige dict = words (voir les fichiers d’exemples).

[1Si cela s’avère nécessaire, on pourra séparer les deux en sortant de Fulltext le code utile à la manœuvre.