"where contains" à la place de "like"

alexxxxx
Invité n'ayant pas de compte PHPfrance

04 janv. 2012, 00:07

Bonjour,

Je cherche à faire une recherche de texte sur les titres du livre (une trentaine de caractères maximum). Je procède en gros comme cela :
req="(SELECT a.title, a.subtitle, a.author FROM Book a WHERE ";
$words = explode(' ', $params['search']);
$num_words = count($words);
for ($i = 0; $i<$num_words; $i++) {
$req .= 'title LIKE :word'.$i.'';
     if (($i + 1) != $num_words) {
	     $req .= " AND ";
      }
}
$req.=')';
for ($i = 0; $i < $num_words; $i++) {
       $reponse_count->bindValue(':word'.$i.'', "%" . $words[$i] . "%");
}

Après quelques lectures sur le net j'ai appris qu'il n'était pas très recommandé de faire des requêtes du genre car peu optimisé.
Je me suis inspiré de ça :http://www.grafactory.net/blog/post/200 ... avec-Mysql pour faire une recherche fulltext sur une autre table que j'appelle "text_search" de type MyIsam mais je n'arrive pas a transformer ma requête pour qu'elle marche. Je pensais à quelque chose comme ça :
req="(SELECT a.title, a.subtitle, a.author FROM Book a  INNER JOIN text_search s ON a.ID=s.ID WHERE CONTAINS(s.title, ";
$req .= ':word'.$i.'';
     if (($i + 1) != $num_words) {
	     $req .= " and ";
      }
}
for ($i = 0; $i < $num_words; $i++) {
       $reponse_count->bindValue(':word'.$i.'', $words[$i]);
}
Ce n'est pas bon mais je ne sais pas comment faire. Quelqu'un pour m'aiguiller? Merci :)

Mammouth du PHP | 568 Messages

04 janv. 2012, 00:27

Active la gestion des erreurs de PDO afin d'avoir un message ou quelque chose à nous donner afin de t'aiguiller.

Ensuite tu peux toujours afficher ta query dans ta page et l'essayer dans phpMyadmin (ou mysql directement).

ViPHP
ViPHP | 4039 Messages

04 janv. 2012, 10:32

Lis en détail la doc mysql sur la recherche fulltext, tu veras que la bonne requête est du genre
MATCH (...) AGAINST (...)
http://dev.mysql.com/doc/refman/5.0/fr/ ... earch.html
Mais qu'importe. (je suis ici - dernier petit projet)
Berze going social.

alexxxxx
Invité n'ayant pas de compte PHPfrance

04 janv. 2012, 10:49

Bonjour,

En fait ma requête fonctionne mais me retourne un résultat vide alors que j'obtiens bien le résultat voulu avec "like" ...

alexxxxx
Invité n'ayant pas de compte PHPfrance

04 janv. 2012, 11:15

Ca y est j'ai compris, il me semble : contains est la syntaxe pour microsoft sql et pour oracle mysql, il faut utiliser match against. Merci Berzemus

alexxxxx
Invité n'ayant pas de compte PHPfrance

04 janv. 2012, 12:17

J'en profite pour poser une autre question concernant la recherche avec match against.
Je fais comme ceci :
req="(SELECT a.title, a.subtitle, a.author FROM Book a  INNER JOIN text_search s ON a.ID=s.ID WHERE MATCH(s.title) AGAINST(
for ($i = 0; $i<$num_words; $i++) {
$req .= ':word'.$i.'';
     if (($i + 1) != $num_words) {
             $req .= "  ";
      }
}
$req.='IN BOOLEAN MODE';
for ($i = 0; $i < $num_words; $i++) {
       $reponse_count->bindValue(':word'.$i.'', "+" .$words[$i]);
}
Le souci est que seul le premier mot est pris en compte. Mais si je fais une recherche avec plusieurs mot, les mots suivants ne semblent pas pris en compte. Pourtant j'ai bien mis les '+'. J'ai fais un test directement dans phpMyadmin ...
 req="(SELECT a.title, a.subtitle, a.author FROM Book a  INNER JOIN text_search s ON a.ID=s.ID WHERE MATCH(s.title) AGAINST('+bla +bli' IN BOOLEAN
MODE))
et la ça marche bien, il me trouve les titres contenant 'bla' et 'bli'. Je suppose qu'il y a quelque chose au niveau des '+' qui ne sont pas pris en compte...

alexxxxx
Invité n'ayant pas de compte PHPfrance

04 janv. 2012, 21:55

Bon j'ai trituré ma requête dans tous les sens et pas moyen faire valoir les mots de recherche autre que le premier :'( Quelqu'un saurait m'aider ?

ViPHP
ViPHP | 4039 Messages

05 janv. 2012, 13:58

Si la requête marche du côté phpmyadmin mais pas du côté php, fait un echo sur la variable qui contient ta requête avant de l'exécuter, pour t'assurer qu'elle correspond bien ce à quoi tu t'attends.
Mais qu'importe. (je suis ici - dernier petit projet)
Berze going social.

alexxxxx
Invité n'ayant pas de compte PHPfrance

05 janv. 2012, 15:30

Salut,

Je crois avoir compris d'ou vient le problème mais je ne sais pas comment le résoudre. La requête est comme ça :
req="(SELECT a.title, a.subtitle, a.author FROM Book a  INNER JOIN text_search s ON a.ID=s.ID WHERE MATCH(s.title) AGAINST(:word0 :word1 IN BOOLEAN MODE))
Après le bindvalue, il me semble qu'elle devient comme ça :
req="(SELECT a.title, a.subtitle, a.author FROM Book a  INNER JOIN text_search s ON a.ID=s.ID WHERE MATCH(s.title) AGAINST('+bla'  '+bli' IN BOOLEAN MODE))
Ca passe coté syntaxe mais moi je veux '+bla +bli' et pas '+bla' '+bli'.

Eléphant du PHP | 209 Messages

05 janv. 2012, 15:37

Dans ce cas, il faut que tu fasses un seul bindValue comportant l'ensemble de tes mots.
Il te suffit de préparer ta chaîne dans la boucle et de faire le bind à la fin.

alexxxxx
Invité n'ayant pas de compte PHPfrance

05 janv. 2012, 16:47

Oui, je vais faire comme ça :p je ne vois pas d'autre solution. Merci beaucoup :!: