8791 sujets

Développement web côté serveur, CMS

Bonjour,

Je cherche a savoir comment faire pour trier les résultats d'une requête selon la pertinence des mots.

Si par exemple je tape ciel et soleil dans le formulaire de recherche je voudrai que les premiers résultats a s'afficher traite ces deux mots ensemble et que les suivant traite indépendemment les autres mots.

En clair un résultats contenant :

a écrit :
1. Ciel et Soleil

2. Ciel

3. Soleil


Un autre exemple avec chat souris chien

a écrit :
1. Chat Souris Chien

2. Chat Souris

3. Souris Chien

4. Chat Chien

5. Chat

6. Chien

7. Souris


Mes exemples sont un peu simple mais résument bien ce que je désire faire

Cordialement
Modifié par kilian67 (22 Aug 2007 - 00:58)
Salut kilian67 Smiley cligne ,

il se trouve que je suis en train de m'amuser avec le même jouet Smiley lol !

Donc si ça peut t'aider, voilà où j'en suis :

1ère solution) génération d'une requête avec des UNION (la recherche est limitée à 5 mots MAXI). Je suis sous PHP5 mais il me semble que ça fonctionne également avec PHP4. Au pire il faudrait lancer les requêtes les unes après les autres.

Quelques remarques :
- les tests sont efféctués sur une table recherche qui contient 2 champs (id et Texte)
- le paramètre envoyé à la fonction provient directement du champ Rechercher.
- à chaque mot est attribuée une valeur (1, 2, 4, 8, 16) pour pouvoir effectuer le tri
- plutôt que de recalculer l'ordre en fonction du nombre de mots je l'ai mis en dur dans le tableau tri... Par exemple, 31 correspond aux 5 mots (1 + 2 + 4 + 8 + 16), 23 correspond à 4 mots ( 1+ 2 + 4 + 16), etc...
- pour bien faire il faudrait vérifier les caractères du champ $texte en entrée (preg_replace...)

Ce qui donne pour l'instant :
<?php
function sqlsearch($texte) {
	$mot = array();
	$search = array();
	$mots = explode(" ", $texte);
	$nb = count($mots);
	$j = 0;
	for ($i = 0; $i < $nb; $i++) {
		$mots[$i] = trim($mots[$i]);
		if ($mots[$i] != '') {
			$mot[] = $mots[$i];
			$valeur[$j] = pow(2, $j);
			$j++;
		}
	}
	$nb = count($mot);
	if ($nb == 0) {
		return 'rien';
	}
	if ($nb > 5) {
		return 'trop';
	}
	$valeur = array_reverse ($valeur);
	$tri = array (
		5 => '31,30,29,27,23,15,28,26,25,22,21,19,14,13,11,7,24,20,18,17,12,10,9,6,5,3,16,8,4,2,1',
		4 => '15,14,13,11,7,12,10,9,6,5,3,8,4,2,1',
		3 => '7,6,5,4,3,2,1',
		2 => '3,2,1',
		1 => '1');
	$nombre = explode(",", $tri[$nb]);
	foreach($nombre as $id => $val) {
		for ($i = 0; $i < $nb; $i++) {
			if($val >= $valeur[$i]) {
				$search[$id][] = $mot[$i];
				$val -= $valeur[$i];
			} 
		}
	}			
	$requete = '';
	for($i = 0; $i < count($search); $i++) {
		$requete .= 'Select id from recherche where ';
		for($j = 0; $j < count($search[$i]); $j++) {
			$requete.= "Texte like '%".$search[$i][$j]."%' ";
			if ($j < count($search[$i]) - 1) {
				$requete .= 'and ';
			}
		}
		if ($i < count($search) - 1) {
			$requete .= 'union ';
		}
	}			
return $requete;	
}

$sql = sqlsearch('  chien  chat souris  cheval dragon');
echo $sql;
?>

2ème solution) Une autre solution serait d'effectuer une seule requête du genre :
Select id, Texte from recherche where Texte like '% dragon %' and Texte like '% cheval %' and Texte like '% souris %' and Texte like '% chat %' and Texte like '% chien %'
puis de relire tous les résultats en attribuant une note à chaque ligne en fonction du nombre de mots présents dans Texte (utilisation de preg_match).
Et enfin trier la table avant affichage...

En espérant que cela t'aidera...

A+ Smiley smile
Modifié par Heyoan (23 Aug 2007 - 00:09)