Bon, voila comment j'ai procédé, mais cela peut être adapté suivant les commentaires que vous pourrez faire.
Je prend un exemple pour simplifier (issu de la base de bueil) et assez tordu en même temps pour me permettre de pointer un des problèmes de la recherche par titre où il n'y a pas d'autorités (et ça, on n'y pourra jamais rien...) Rappel du problème : l'utilisateur fournit une chaîne. la chaîne est divisée en mots. si tous les mots ont plus de trois caractères, on utilisera la méthode MATCH/AGAINST (fulltext). si les ou un des mots comprennent 3 ou moins caractères, on switche sur la recherche REGEXP. Les mots vides sont éliminés de la requête utilisateur (le, la, les, l', typiquement. Si l'utilisateur a saisi des caractères utilisés dans les masques d'expressions régulières (|$, ^ et autres), j'ai considéré qu'il avait saisi une expression régulière et il n'y a aucun traitement (je pars du principe que dans ce cas, il sait ce qu'il fait). Là dessus vient se greffer la nécessité de retourner un indice de pertinence pour chaque résultat retourné (tri par ordre décroissant de pertinence + on fera une petite image pour visualiser l'indice de confiance du résultat). Je prend l'exemple 'vietnam' saisi en recherche titre Le mot fait plus de 4 caractères, donc MATCH/AGAINST : la requête générée par la fonction test_title_query() est : select *,MATCH (index_tit1,index_tit2,index_tit3, index_tit4, index_serie) AGAINST ('vietnam') AS indice from notices WHERE MATCH (index_tit1,index_tit2,index_tit3, index_tit4, index_serie) AGAINST ('vietnam') ORDER BY MATCH (index_tit1,index_tit2,index_tit3, index_tit4, index_serie) AGAINST ('vietnam') DESC 1 résultat avec son indice de pertinence : Ho Chi Minh 7.2678657682646 Ca colle : le sous-titre est 'de l'Indochine au Vietnam' donc c'est normal que ça sorte. Cependant, je trouve ça bizarre parce que j'ai un peu parcouru la base de Bueil. J'ai l'impression que je devrais avoir plus de résultats. Comme je suis un bibliothécaire avec de l'expérience ;-), je me dis : 'à 100 contre un, la BDT a saisi vietnam avec un tiret !!!' (les deux orthographes sont admises et la rêgle de catalogage dit qu'on doit saisir le titre exactement comme il figure sur la page de titre du livre). De toutes les façons, pour cet exemple, je suis sûr que les trois quarts des gens seraient passés par la recherche catégorie où c'est une autorité, donc le problème se lève. On aurait pu faire aussi en titre 'vietnam|viet-nam' pour aboutir, mais il faut connaître un peu les regexp... Je saisis donc 'viet-nam'. première chose que fait la fonction test_title_query() : virer le tiret pour diviser tout ça en mots (de toute façon, il est exclu de index_tit1 quand on fait le 'pseudo- index' qui sert à la recherche). Ca devient 'viet nam' (mot avec moins de 4 caractères : on switche en regexp). La requête générée est : select *,5*(index_serie REGEXP 'viet') + 4*(index_tit1 REGEXP 'viet') + 3*(index_tit4 REGEXP 'viet') + 2* (index_tit3 REGEXP 'viet') + 1*(index_tit2 REGEXP 'viet') + 5*(index_serie REGEXP 'nam') + 4*(index_tit1 REGEXP 'nam') + 3*(index_tit4 REGEXP 'nam') + 2*(index_tit3 REGEXP 'nam') + 1*(index_tit2 REGEXP 'nam') AS indice from notices WHERE (index_serie REGEXP 'viet' OR index_tit1 REGEXP 'viet' OR index_tit2 REGEXP 'viet' OR index_tit3 REGEXP 'viet' OR index_tit4 REGEXP 'viet') AND (index_serie REGEXP 'nam' OR index_tit1 REGEXP 'nam' OR index_tit2 REGEXP 'nam' OR index_tit3 REGEXP 'nam' OR index_tit4 REGEXP 'nam') ORDER BY 5*(index_serie REGEXP 'viet') + 4*(index_tit1 REGEXP 'viet') + 3*(index_tit4 REGEXP 'viet') + 2* (index_tit3 REGEXP 'viet') + 1*(index_tit2 REGEXP 'viet') + 5*(index_serie REGEXP 'nam') + 4*(index_tit1 REGEXP 'nam') + 3*(index_tit4 REGEXP 'nam') + 2*(index_tit3 REGEXP 'nam') + 1*(index_tit2 REGEXP 'nam') DESC, index_serie DESC, index_tit1 ASC Joli non ? Le AND du milieu de la requête est généré suivant un paramètre qu'on passe à la fonction. Suivant la valeur, ce sera AND ou OR (bouton radio dans le form de recherche : tous les mots/au moins un des mots). Ca me retourne deux résultats (avec indice de pertinence) : Viêt-Nam 8 Ho Chi Minh 6 C'est mieux déjà. J'ai fixé l'indice de la façon suivante : si la séquence figure dans le titre de série, j'attribue un facteur de 5. Si elle est dans le titre propre un facteur de 4. sous-titre, etc... Le tout est trié sur indice de pertinence décroissant, titre de série décroissant (pour avoir les séries au début) et titre propre ascendant (pour trier quand même si l'indice est identique). résultat des courses : pour moi, ça marche (j'en suis même assez content car cela élimine un certain bordel en recherche fulltext). Le bémol est dû à la nature même de la recherche par titre : il faut réfléchir des fois. Le problème du tiret est insoluble d'ailleurs : comment faire comprendre au logiciel que ça peut être une limite de mot et parfois pas une limite de mot ?-) Jetez y un coup d'oeil (c'est dans ./includes/misc.inc.php). Si c'est OK pour vous, j'implémente ça dans le biniou en vrai et on aura la recherche avec les opérateurs booléens !!! J'ai encore un petit truc à résoudre : il faudrait pour faire la minibarre retourner aussi l'indice maximum pour la recherche en cours. C'est pas difficile, je m'en vais vérifier que la fonction MAX existe en MySQL... A+ Selon François Lemarchand <[EMAIL PROTECTED]>: > Je vois qu'il y a du monde même le dimanche ;-) > > Je suis sur la refonte de la recherche titre. Pour > l'instant, je bosse sur une fonction 'test_title_query()' > > dans misc.inc.php. Normalement, ça vient remplacer > analyze_title_query(). > > Ca commence comme ça (le reste est commité, mais pas > utilisé encore) : > > function test_title_query($query, $operator=TRUE, > $force_regexp=FALSE) > { > // fonction d'analyse d'une recherche sur titre > // la fonction retourne un tableau : > > $query_result = array( 'type' => 0, > 'restr' => '', > 'order' => ''); > // $query_result['type'] = type de la requête : > // 0 : rien (problème) 1: match/against 2: regexp > // $query_result['restr'] = critères de restriction > // $query_result['order'] = critères de tri > > // si operator TRUE La recherche est booléenne AND > // si operator FALSE La recherche est booléenne OR > // si force_regexp: la rech. est forcée en mode > regexp > ... > > Si je cherche 'mouvement libération femme' avec recherche > > regexp forcée, j'obtiens ce restricteur : > > WHERE (index_tit1 REGEXP 'mouvement' OR index_tit2 > REGEXP 'mouvement' OR index_tit3 REGEXP 'mouvement' OR > index_tit4 REGEXP 'mouvement' OR index_serie > REGEXP 'mouvement') AND (index_tit1 REGEXP 'liberation' > OR > index_tit2 REGEXP 'liberation' OR index_tit3 > REGEXP 'liberation' OR index_tit4 REGEXP 'liberation' OR > > index_serie REGEXP 'liberation') AND (index_tit1 > REGEXP 'femme OR index_tit2 REGEXP 'femme' OR index_tit3 > > REGEXP 'femme' OR index_tit4 REGEXP 'femme' OR > index_serie > REGEXP 'femme') > > Ca me paraît OK sur la forme, mais question utilisation > de > ressources ça te dit quoi ? (pas un peu lourd ?). > > J'ai une autre soluce sous le coude : > > WHERE index_tit1 REGEXP 'mouvement|liberation|femme' OR > index_tit2 > REGEXP 'mouvement|liberation|femme' OR index_tit3 > REGEXP 'mouvement|liberation|femme' OR > index_tit4 REGEXP 'mouvement|liberation|femme' OR > index_serie > REGEXP 'mouvement|liberation|femme' > > qui me semble moins gourmande, mais je tiens à appliquer > le > booléen fourni en param même si ça switche sur REGEXP. > > Si je ne force pas la REGEXP, j'obtiens cela (beaucoup > plus > civilisé...) : > > WHERE MATCH (index_tit1,index_tit2,index_tit3, > index_tit4, > index_serie) AGAINST ('mouvement') AND MATCH > (index_tit1,index_tit2,index_tit3,index_tit4, > index_serie) > AGAINST ('liberation') AND MATCH > (index_tit1,index_tit2,index_tit3,index_tit4, > index_serie) > AGAINST ('femme') > > Une fois que j'ai fini le restricteur, reste le problème > de > la création d'un indice de confiance pour les REGEXP. > > apparemment, champ REGEXP 'montruc' me retourne 0 ou 1, > donc si je construit mon indice comme ça : > > SELECT stuff, champ1 REGEXP 'truc' + champ2 REGEXP 'truc' > > + ... AS indice > > j'obtiens une approximation d'un simili indice ? > > (je m'occuperais de la mise à l'echelle pour la > mini-barre > sur le moment de sa génération...) > > A+ > > -- > François Lemarchand > homepage : http://balno.free.fr/ > PhpMyBibli : http://phpmybibli.sourceforge.net > > Liste de diffusion phpmybibli.devel > Pour se désinscrire : > mailto:[EMAIL PROTECTED] subject=unsubscribe > > -- François Lemarchand homepage : http://balno.free.fr/ PhpMyBibli : http://phpmybibli.sourceforge.net Liste de diffusion phpmybibli.devel Pour se désinscrire : mailto:[EMAIL PROTECTED]