Développer un moteur de recherche en PHP.

WRInaute accro
Hello,

Pour le site dont je m'occupe, j'aimerais vraiment développer un moteur de recherche assez poussé. Pour le moment, mon moteur se base sur un truc assez basique du genre : http://www.phpinfo.net/articles/article_moteur.html .

Je me suis basé sur l'architecture de PhpDig ( http://www.phpdig.net ) pour ma base de données qui est la plus optimisée possible, je pense. Mais là, je commence à avoir des doutes...

Avez-vous quelques articles ou tutoriels sous le coude pour développer quelques choses d'assez poussé ?

Je vous demande ça car au fil de mes recherches, je ne tombe que sur des articles pour "débutant"...
 
WRInaute accro
Bon bé puisque personne ne me répond, je vais vous faire part de mes différents tests et recherches. Le site en question est un site e-commerce. Le moteur doit recherché dans les fiches produits.


Ce moteur a pour but de proposer des résultats pertinents aux recherches des visiteurs du site.


ARCHITECTURE OPTIMISEE DE LA BDD
----------------------------------------------------------


-----------------------------------------------------------
| SEARCH_KEYWORDS |
-----------------------------------------------------------
| keyword VARCHAR(255) UNIQUE |
| key_id INT(11) PRIMARY KEY AUTO INCREMENT |
-----------------------------------------------------------


---------------------------------------------
| SEARCH_ENGINE |
---------------------------------------------
| key_id INT(11) INDEX |
| weight TINYINT(2) |
| ref_prod VARCHAR(15) INDEX |
---------------------------------------------


keyword : mot clé
key_id : identifiant du mot clé
weight : poids du mot clé
ref_prod : référence du produit



PHASE D'INDEXATION
-------------------------------------------------------------

1- Pour chaque produit, on sélectionne sa famille, sa marque, sa désignation, son descriptif
2- On transforme chaque chaine : on enleve les tags HTML, les backslashes et on met tout en minuscule.

Ensuite, on transforme les caractères spéciaux en caratères HTML grâce à la fonction HTML entities
3- On remplace les caractères génants par des espaces. Exemple de caractères génants : ,.+-*/:=()'!?%, " &euro < > etc...
4- On transforme les accents : Par exemple, é->e, è->e, etc...
5- A chaque type de champ, on associe un poids des mots. Par exemple, les mots contenus dans la désignation pourront avoir un poids de 99, ceux compris dans la marque pourront avoir un poids de 30, ceux dans le descriptif de 1.
6- Pour chaque type de champ, on explose la chaine et on stocke chaque mot dans 1 tableau.
7- Pour chaque mot :

. Si le mot n'est pas insérer dans SEARCH_KEYWORDS, on l'insère et on insère son identifiant, son poids et la référence du produit dans SEARCH_ENGINE
. Sinon, on sélectionne son identifiant dans SEARCH_KEYWORDS et on l'insère dans SEARCH_ENGINE avec son poids et la référence du produit.

L'étape d'indexation est finie ! Bien sûr, il faut optimiser le tout, parce que si vous avez comme moi plus de 3000 produits avec de bonnes grosses fiches, vous allez exploser votre serveur MySQL


PHASE DE RECHERCHE
--------------------------------------------------------------

1- on met en place un formulaire tout con avec un champ recherche
2- Lorsque la chaine de recherche est envoyée, on nettoie la chaine (on enleve les tags HTML, les backslashes et on met tout en minuscule. Ensuite, on transforme les caractères spéciaux en caratères HTML grâce à la fonction HTML entities. On remplace les caractères génants par des espaces. Exemple de caractères génants : ,.+-*/:=()'!?%," &euro < > etc... On transforme les accents : Par exemple, é->e, è->e, etc...
3- On explose la chaine en mots clés.
4- On boucle pour supprimer les caractères courants (de, le, un, une, ...)
5- On fait une requête sur notre base de données en comparant les mots clés (j'utilise OR) et en additionnant le poids des mots.
6- On tri par poids des mots (le plus grand poids s'affichant en premier)
7- On affiche que les résultats qui ont une pertinence supérieure à 50% (on se base sur le poids maximum. Si la somme de tous les poids de mon premier résultats fait 240, on affiche que les résultats dont la somme de leur poids est supérieure à 120)

Voila, j'en suis là pour le moment. Les résultats de mes recherches ont l'air plutôt pas mal du tout. Mais il me reste encore beaucoup de choses à améliorer. J'attend bien sûr vos commentaires !
 
WRInaute accro
Les problèmes que je rencontre pour le moment :
- le singulier et le pluriel
- le calcul du poids des mots peut être faussé à cause de la longueur des textes. Je doit donc calculer un indice de densité (poids des mots par rapport au nombre de mots dans le texte).

Tout ça ne pause pas de problème de traitement, c'est plutôt facile à calculer, mais en terme de ressources, ça en bouffe énormément !
 
WRInaute accro
Et bien merci de ton avis spidetra !
En fait, dans mon cas, le couple PHP / MySQL suffit largement, je pense. J'ai environ 3000 produits et je n'indexe que le contenu de ma base de données (pas de fichier HTML ou PDF).

La phase d'indexation prend beaucoup de ressources, oui. Mais je pense que par la suite, cette phase n'aura plus jamais lieu. En fait, à chaque fois qu'une fiche produit est ajoutée, modifiée ou supprimée dans le backoffice, le programme ne réindexera que cette fiche. Ce sera donc très économique en ressources.

Pour ce qui est de la recherche, pour le moment, mes requêtes sont elles aussi assez économiques en ressources. Le probème, c'est que même si j'ai réussi à améliorer énormément la qualité de mes résultats, il y a toujours mieux à faire...

Je me renseigne pour les espaces vectoriels de Salton (ça fait peur ce nom, quand même). Merci !
 
WRInaute accro
Ouha, merci les gars pour toutes ces infos.

Pour le problème du pluriel / singulier, je m'en tire pour le moment avec une bidouille pour le moment : pour toutes les chaines de plus de 4 caractères, j'enlève le 's' si il y en a un à la fin du mot. Mais bon, ça reste de la bidouille, il faut que je fasse quelquechose de plus carré.

Pour ta question spidetra, j'ai effectivement rajouté un champ à ma table search_engine pour savoir quel type de mot il s'agit (titre, description, famille, marque, ...). Ca me permet de configurer le poids que j'attribue à chaque mot.

Bon, je regarde tout ce que vous venez de me recommander et je vous fais part des résultats de mes stats qui risques d'être très long. (en ce moment, j'analyse la pertinence de plus d'une centaine de requête à chaque fois que je fais une modif).
 
WRInaute accro
Je viens de regarder FULL TEXT. C'est très bien mais ça ne convient pas vraiment à mon cas, car j'ai beaucoup d'info dans ma table qui sont des référénces à d'autres tables. Je vais quand essayer d'approfondir...

Je vais aussi tester la fonction SOUNDEX : peut-être pas pour les résultats mais pour proposer une autre recherche en cas de faute d'orthographe.
 
WRInaute impliqué
Pour le dictionnaire des synonymes, il en existe déjà. Il suffirait de mettre la main sur les mots et leurs synonymes et il suffirait de formater le tout pour que ca soit interprétable comme du PHP (je me propose pour le faire si vous trouvez le dico :mrgreen: )

EDIT : J'ai aussi une fonction qui donne renvoie les SOUNDEX pour la langue francaise, si ca intéresse quelqu'un :)
 
WRInaute impliqué
Soundex version francaise

Code:
function soundex2( $sIn )
{
	// Si il n'y a pas de mot, on sort immédiatement
	if ( empty( $sIn ) ) 
		return null;
	// On met tout en minuscule
	$sIn = strtoupper( $sIn );
	// On supprime les accents
	$sIn = strtr( $sIn, 'ÂÄÀÇÈÉÊËŒÎÏÔÖÙÛÜ', 'AAASEEEEEIIOOUUU' );
	// On supprime tout ce qui n'est pas une lettre
	$sIn = preg_replace( '`[^A-Z]`', '', $sIn );
	// Si la chaîne ne fait qu'un seul caractère, on sort avec.
	if ( strlen( $sIn ) === 1 ) 
		return $sIn;
	// on remplace les consonnances primaires
	$convIn = array( 'GUI', 'GUE', 'GA', 'GO', 'GU', 'CA', 'CO', 'CU',
	'Q', 'CC', 'CK' );
	$convOut = array( 'KI', 'KE', 'KA', 'KO', 'K', 'KA', 'KO', 'KU', 'K',
	'K', 'K' );
	$sIn = str_replace( $convIn, $convOut, $sIn );
	// on remplace les voyelles sauf le Y et sauf la première par A
	$sIn = preg_replace( '`(?<!^)[EIOU]`', 'A', $sIn );
	// on remplace les préfixes puis on conserve la première lettre
	// et on fait les remplacements complémentaires
	$convIn = array( '`^KN`', '`^(PH|PF)`', '`^MAC`', '`^SCH`', '`^ASA`',
	'`(?<!^)KN`', '`(?<!^)(PH|PF)`', '`(?<!^)MAC`', '`(?<!^)SCH`',
	'`(?<!^)ASA`' );
	$convOut = array( 'NN', 'FF', 'MCC', 'SSS', 'AZA', 'NN', 'FF', 'MCC',
	'SSS', 'AZA' );
	$sIn = preg_replace( $convIn, $convOut, $sIn );
	// suppression des H sauf CH ou SH
	$sIn = preg_replace( '`(?<![CS])H`', '', $sIn );
	// suppression des Y sauf précédés d'un A
	$sIn = preg_replace( '`(?<!A)Y`', '', $sIn );
	// on supprime les terminaisons A, T, D, S
	$sIn = preg_replace( '`[ATDS]$`', '', $sIn );
	// suppression de tous les A sauf en tête
	$sIn = preg_replace( '`(?!^)A`', '', $sIn );
	// on supprime les lettres répétitives
	$sIn = preg_replace( '`(.)\1`', '$1', $sIn );
	// on ne retient que 4 caractères ou on complète avec des blancs
	return substr( $sIn . '    ', 0, 4);
}
 
WRInaute impliqué
Je n'ai pas la prétention de dire que c'est moi qui ai développé cette fonction, vu que je n'y connait pas grand chose à phonétique :)

Je suis tombé dessus dans un commentaire de php.net sur la fonction soundex, elle est aussi disponible en version espagnole je crois.

Je pense qu'on peut l'utiliser en enregistrant le soundex de chaque mot, puis on repère les mots similaires grâce à leur prononciation. Genre pour faire une sorte de correcteur :
- L'utilisateur tape : sheval
-> Essayez avec cette orthographe : cheval

Voilou :)
 
WRInaute accro
orvinfait a dit:
Pour tous: Compte tenu du travail plus nous serons nombreux mieux cela sera et comme je l'ai indiqué dans un message précédent même ceux qui ne savent pas programmer peuvent participer.

Tout à fait d'accord, c'est pourquoi je ferais un grand article dès que j'aurais une base solide qui sera bien sûr soumis à vos commentaires. Pour le moment, j'arrive a de très bons résultats (d'après mes tests) mais je suis aussi confronté à des grands problèmes de ressources au niveau du serveur (mon moteur est très lent malgré mes efforts d'optimisation)....

Encore beaucoup de boulot en perspective. Mais plus on aura de lien vers des articles et tutos, plus on aura de base de connaissances sur lesquelles s'appuyer...
 
WRInaute occasionnel
utilise la recherhce full text de mySql, mysqsl a son propore algorithme de calcul de premtinence rank, il est pas mal et ça nécessite aucun développement de votre part.
sinon utilise google :)
 
WRInaute passionné
nodom a dit:
utilise la recherhce full text de mySql, mysqsl a son propore algorithme de calcul de premtinence rank, il est pas mal et ça nécessite aucun développement de votre part.
sinon utilise google :)

Blman, ne veut pas utiliser la fonction full-text de MySQL.
Un site de e-commerce ne peut pas confier sa recherche interne à Google.
 
WRInaute passionné
blman a dit:
Comme déjà dit, Full Text ne correspond pas très bien à mes besoin. Par contre, j'ai aussi pensé à utiliser Google, on verra... (le problème, c'est que l'index de Google n'est pas très frais...)

nos messages se sont croisés !
 
WRInaute impliqué
Je me souvenais plus du post initial, j'etais parti dans le developpement d'un moteur de recherche interne ^^ desole :(

Spidetra : oui je parlais de la fonction soundex version fr pas de celle initiale hein :) Et puis moi je proposerais plutot une biere aux alentours de Paris :mrgreen:
 
WRInaute discret
Sympa cette dicsussion !!

Je voulais savoir ce que vous pensiez du moteur cité dans ce post : http://developpeur.journaldunet.com/dos ... teur.shtml

Est-il performant? Je voudrais le modifier pour qu'il puisse gérer une recherche multi-mots. Est-ce que vous me confortez dans ce choix de moteur ou est-ce que vous pensez que ce moteur n'est pas terrible?

Le moteur de recherche que je veux développer doit gérer plus de 2000 pages avec environ 100 mots par page minimum et permettre une recherche multi-mot relativement rapide (2 à 3 secondes max). Est-ce satifaisant ?

Merci pour toutes vos réponses et merci encore à tous ceux qui m'en apprennent vachement sur les moteur (spidetra) :wink:
 
WRInaute accro
Bonjour evets,

l'article du JDN ressemble assez à ce que je voulais faire. Je n'ais toujours pas réussi à coder quelquechose qui soit performant et pertinant (je n'y ais peut-être pas passé le temps nécéssaire).

En tout cas, j'ai eu récemment une discussion avec un responsable d'Antidot, le moteur de recherche interne. On m'a dit que des recherches aussi complexes ne pouvaient pas se faire avec des langages de type SQL.

Voila, c'est juste pour info. Ils essayaient surement de me vendre leurs solutions mais j'ai l'impression qu'il faut être vraiment balaise pour faire quelqechose de très performant en PHP/MySQL.
 
WRInaute discret
Superbe topic que je viens de trouver là. Moi aussi j'ai commencé la prog d'un moteur de recherche en php/sql.

Le but caché étant de devenir plus performant que phpdig en terme de rapidité et pertinance. D'ailleurs je pense que il y a moyen d'optimiser phpdig pour gagner quelques ms.

J'ai commencé mon projet depuis une paire de semaine seulement et j'en suis toujours à la partie indexation.
Cette dernière est vraiment compliqué à mettre en place, puisque je compte utiliser une sorte de "pagerank".

Je vais donc bien surveillez ce topic ;)
 
Nouveau WRInaute
blman a dit:
Je viens de regarder FULL TEXT. C'est très bien mais ça ne convient pas vraiment à mon cas, car j'ai beaucoup d'info dans ma table qui sont des référénces à d'autres tables. Je vais quand essayer d'approfondir...

Je vais aussi tester la fonction SOUNDEX : peut-être pas pour les résultats mais pour proposer une autre recherche en cas de faute d'orthographe.


Le soundex est une cle base sur un algo de langue anglaise...si bien que "audience" est considéré comme différent de "odience" (sic)...

Aussi, pour faire une chose "propre/clean" dans votre moteur, vous devez au moins déterminer la langue du document avant d'en faire l'indexation...cela passe aussi par la detection de charset...et sa transcription dans votre charset perso ...(je vous conseille UTF-8 !!)

Quant à Salton..c'est une bonne approche qui devient vite bizarre surtout si un document contient une grande quantite d'un même mot. Il est surexpose comme dans google 95 ! (souvenez vous ;) )

Bon courage..vous etes sur la bonne voie
 
WRInaute accro
thierry8 a dit:
au passage pourquoi tous les posts de spidetra sont "effacé" (édité je suppose)

Parce que Spidetra ne traine plus sur ce forum. Il a voulu éditer certains messages à son départ. Dommage, pour le connaitre un peu, je peux dire qu'on a perdu quelqu'un de vraiment compétent :cry:
 
WRInaute impliqué
Très intéressant ce topic ! J'essaie moi aussi de coder un petit moteur (php 5) avec classement par pertinence. Le point central à mon avis c'est d'intégrer dans l'algo la proximité entre les mots (plus les mots clés recherchés sont proches dans le contenu et plus ce contenu est un bon résultat), et la possibilité de chercher dans des fichiers physiques (2 choses qu'on ne peut pas faire avec mysql 5 en mode fulltext).

Et bien sûr que ça puisse fonctionner sur un mutu avec 16M de mémoire php et toutes les autres restrictions.
 
Nouveau WRInaute
Topic effectivement très intéressant, je suis moi aussi sur une problèmatique de création de moteur de recherche (Php+MySQL).

Je vais tout d'abord potasser toutes les choses mentionnées jusqu'à présent avant de vous faire un retour si j'ai quelque chose de pertinent à proposer.

Si quelqu'un a conserver les liens de spidetra cela m'intéresserait de les consulter....

L'un d'entre vous sait comment faire pour configurer MySQL afin d'utiliser un dico FR (ou EN, ES,...); peut-on le faire dynamiquement (selon l'origine du visiteur par ex) ou est-ce au démarrage du serveur mySQL ?

Je pense notamment aux stopwords et aux dico des recherches fullText.
 
WRInaute occasionnel
bonjour. je relance ce sujet car j'ai également développé mon propre algo;
il fonctionne comme décris ci-dessous :
- je recherche les mots clé et affecte un poids à chaque match.
- je calcule donc une valeur 'pertinence' que j'affecte à chaque produit directement dans la base de donnée.

mais j'ai un énorme problème que je ne voyais pas au début : le trafic de mon site à tripler en un an et donc, il arrive en permanence qu'un internaute fasse une recherche XXX. je calcule donc la pertinence pour admettons 200 produits sur 5000 concernés par cette recherche et lui affiche les résultats. je lui propose également de faire des clés de tri. le problème c'est qu'entre le moment ou l'interanute clic sur une clé de tri, un autre internaute a pu faire une recherche YYY qui reclacule le champ pertinence.
quelqu'un a-t-il une idée ?
 
WRInaute passionné
JeromeRookie a dit:
bonjour. je relance ce sujet car j'ai également développé mon propre algo;
il fonctionne comme décris ci-dessous :
- je recherche les mots clé et affecte un poids à chaque match.
- je calcule donc une valeur 'pertinence' que j'affecte à chaque produit directement dans la base de donnée.

mais j'ai un énorme problème que je ne voyais pas au début : le trafic de mon site à tripler en un an et donc, il arrive en permanence qu'un internaute fasse une recherche XXX. je calcule donc la pertinence pour admettons 200 produits sur 5000 concernés par cette recherche et lui affiche les résultats. je lui propose également de faire des clés de tri. le problème c'est qu'entre le moment ou l'interanute clic sur une clé de tri, un autre internaute a pu faire une recherche YYY qui reclacule le champ pertinence.
quelqu'un a-t-il une idée ?
ben tu stocke le resultat d'une recherche, et tu fais ensuite de temps en temps ta "google dance" en mettant a jour les resultats. pour les plus populaire, tu peux faire un mise a jour de la recherche toutes les 24heures, ou bien toute les heures, a toi de voir la frequence de mise a jour de ta base.
 
Discussions similaires
Haut