Création d'un moteur de recherche : problème sur la requête

Fermé
HugoC - Modifié le 16 avril 2020 à 00:44
 HugoC - 16 avril 2020 à 18:12
Bonjour et merci à tous ceux qui lissent ce poste
Je suis à la création d'un moteur de recherche protégeant la vie privée de l'utilisateur, mais bon la question n'est pas ici.

Je suis à la recherche d'une requête SQL qui pourrait répondre à mes attentes, voici ma requête actuelle :

SELECT * FROM `site` WHERE title LIKE '%$query%' OR url LIKE '%$query%' 
OR description LIKE '%$query%' 


Sauf que des problèmes persistent comme par exemple l'utilisateur recherche "Cuisine développeur artisan"

La requête n'aboutira pas pour la simple raison : il manque un de ses mots (ou plusieurs).


Cela fait déjà quelque temps que je cherche et mes recherches n'aboutissent pas, aurait-il un moyen de trouver tous les résultats de recherche correspondant à "cuisine développeur artisan" (en suivant l'exemple)

Je préviens pour la variable $query : elle est remplie par l'utilisateur donc elle peut changer.

Je vous remercie d'avance de l'attente que vous pourrez me consacrer. merci !
A voir également:

6 réponses

jee pee Messages postés 39637 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 25 avril 2024 9 235
16 avril 2020 à 00:43
Bonjour,

Déjà, il faudrait découper la chaine saisie en autant de variables (ou un tableau) que de mots et constituer la commande sql dynamiquement en fonction du nombre de mots.

Puis en fait il faudrait quelque chose comme un LIKE IN (aaa,bbb,...).

En sql Oracle ou Sql Server il y a l'instruction CONTAINS quelque chose comme
WHERE CONTAINS(title, '%Cuisine% OR %développeur% OR %artisan%', 1) > 0

ou
WHERE CONTAINS(title, '*Cuisine*' OR '*développeur*' OR '*artisan*') 


Ou pour PostgreSQL un LIKE ANY()

Mais cela n'existe pas dans Mysql :-/

Alors il faut multiplier les where autant de fois que de mots
WHERE title LIKE  '%Cuisine%' 
OR title like '%développeur%' 
OR title LIKE '%artisan%'


Ou multiplier les SELECT
SELECT * FROM `site` WHERE title LIKE '%Cuisine%' OR url LIKE '%Cuisine%' OR description LIKE '%Cuisine%'
union
SELECT * FROM `site` WHERE title LIKE '%développeur%'  OR url LIKE '%développeur%'  OR description LIKE '%développeur%' 
union
SELECT * FROM `site` WHERE title LIKE '%artisan%' OR url LIKE '%artisan%' OR description LIKE '%artisan%'


Certains penchent pour un REGEXP : https://stackoverflow.com/questions/1127088/mysql-like-in

Bien penser aussi a convertir le champ et les valeurs recherchées soit tout minuscule, soit tout majuscule.

Puis il faudrait que tu réfléchisses, si l'utilisateur donne 3 mots, à rechercher dans 3 champs est-ce que 1 concordance pour 9 possibilités c'est suffisant ou il en faut 2, 4 ... Là cela risque de compliquer car il faudrait donner un poids pour chaque mot trouvé.

Cdlt
0
jordane45 Messages postés 38145 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 25 avril 2024 4 650
16 avril 2020 à 08:47
Bonjour,

En mysql il est possible de faire un truc du genre
SELECT * 
FROM  site
WHERE 
MATCH ( title, url, description) 
AGAINST ('+first_word +second_word +third_word' IN BOOLEAN MODE);

https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html

.
0
jee pee Messages postés 39637 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 25 avril 2024 9 235
16 avril 2020 à 10:30
bonjour, oui c'est exactement cela ;-) la recherche plein texte avec classement/poids/pertinence/score.

Même dans Oracle je n'ai pas eu l'occasion d'utiliser cela, c'est un domaine à part entière, avec un paramétrage d'index, thesaurus, ...
0
Merci à tous pour vos réponses des plus complète,

Je ne saisit pas comment ce code peux, "ignorer" les mots qui n'y sont pas, pouvez-vous m'expliqué ? Merci d'avance !
SELECT * 
FROM site
WHERE
MATCH ( title, url, description)
AGAINST ('+first_word +second_word +third_word' IN BOOLEAN MODE);



J'ai essayé ce code, une erreur apparaît :
Erreur dans la requête (1191): Can't find FULLTEXT index matching the column list

Quelqu'un peux m'indiqué ?
0
jordane45 Messages postés 38145 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 25 avril 2024 4 650
16 avril 2020 à 15:01
Comme indiqué dans le lien que je t'ai donné ( et qu'il faut lire...)

InnoDB tables require a FULLTEXT index on all columns of the MATCH() expression to perform boolean queries. Boolean queries against a MyISAM search index can work even without a FULLTEXT index, although a search executed in this fashion would be quite slow.
0
Merci d'avoir répondu aussi rapidement,

Effectivement, j'ai fait les modifications nécessaire qui est passé title, description et url en FULLTEXT, pour l'instant tout va bien, l'hors de l'execution de la requête il me dit
Erreur dans la requête (1191): Can't find FULLTEXT index matching the column list


Et pourtant les colonnes sont bien en FULLTEXT, pouvez-vous m'aidé ? Merci encore !
0
jordane45 Messages postés 38145 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 25 avril 2024 4 650
16 avril 2020 à 17:47
Fais nous un show create de ta table et montre le nous.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Petit update depuis,

SELECT pub, clic, LOWER(title) as title, LOWER(url) as url, LOWER(description) as description2 FROM `site` WHERE MATCH (`title`) AGAINST ('$query' IN BOOLEAN MODE) OR MATCH (`description`) AGAINST ('$query' IN BOOLEAN MODE) OR MATCH (`url`) AGAINST ('$query' IN BOOLEAN MODE) ORDER BY clic DESC LIMIT 10



J'avance petit à petit,

1. Cette requête marche mais es-ce il y a un moyen d'optimiser ?
2. Je n'arrive pas ajouté un moyen pour récupérer les résultats sans LOWER.
3. Il y a t'il un moyen de faire plus pertinent ? (les recherches qui correspondent le mieux par exemple)


Je demande beaucoup, et vous y répondez, je vous remercie sincèrement !
0
jordane45 Messages postés 38145 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 25 avril 2024 4 650
16 avril 2020 à 18:00
Pour ton index.. tu l'as bien créé sur les trois colonnes où tu cherches ?
Là, j'ai l'impression que tu ne l'as mis que une par une...
C'est comme ça qu'il faut le créer
ALTER TABLE tabl1 ADD FULLTEXT INDEX (column1, column2,columnx);


Concernant le "ranking",
Regarde l'exemple donné sur le lien que je t'ai donné
mysql> CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title,body)
) ENGINE=InnoDB;
Query OK, 0 rows affected (1.04 sec)

mysql> INSERT INTO articles (title,body) VALUES
('MySQL Tutorial','This database tutorial ...'),
("How To Use MySQL",'After you went through a ...'),
('Optimizing Your Database','In this database tutorial ...'),
('MySQL vs. YourSQL','When comparing databases ...'),
('MySQL Security','When configured properly, MySQL ...'),
('Database, Database, Database','database database database'),
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL Full-Text Indexes', 'MySQL fulltext indexes use a ..');
Query OK, 8 rows affected (0.06 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> SELECT id, title, body, MATCH (title,body)  AGAINST ('database' IN BOOLEAN MODE)
AS score FROM articles ORDER BY score DESC;
+----+------------------------------+-------------------------------------+---------------------+
| id | title                        | body                                | score               |
+----+------------------------------+-------------------------------------+---------------------+
|  6 | Database, Database, Database | database database database          |  1.0886961221694946 |
|  3 | Optimizing Your Database     | In this database tutorial ...       | 0.36289870738983154 |
|  1 | MySQL Tutorial               | This database tutorial ...          | 0.18144935369491577 |
|  2 | How To Use MySQL             | After you went through a ...        |                   0 |
|  4 | MySQL vs. YourSQL            | When comparing databases ...        |                   0 |
|  5 | MySQL Security               | When configured properly, MySQL ... |                   0 |
|  7 | 1001 MySQL Tricks            | 1. Never run mysqld as root. 2. ... |                   0 |
|  8 | MySQL Full-Text Indexes      | MySQL fulltext indexes use a ..     |                   0 |
+----+------------------------------+-------------------------------------+---------------------+
8 rows in set (0.00 sec)
0
Effectivement pour le fulltext, je l'avais ajouté un par un. Une erreur de ma part.

Pour le ranking, je n'avais pas pensé à la méthode, si je comprend bien celui qui à le plus de correspondance dans url, title et description aura un score élevé ?

Je viens aussi de voir pour les minuscules et majuscule (exemple "teste" et "Teste") et cela marche c'est effectivement ce que je voulais, j'aurais une autre question et surement la derrière

Pour le order by peut t'il y avoir deux argument "ORDER BY score, clic (afin de mettre le site le plus visité en premier) ?

Et niveau performance je sens un ralentissement y a t'il une parade ?

Je te remercie vraiment !
0