| 13 Fonctions à utiliser dans les clauses SELECT et WHERE
 Manuel de Référence MySQL 4.1 : Version Française
 
 . Opérateurs et fonctions tous types
 . Les fonctions de contrôle
 . Fonctions de chaînes de caractères
 . Fonctions numériques
 . Fonctions de dates et d'heures
 ->Recherche en texte intégral ( Full-text ) dans MySQL
 . Fonctions de transtypage
 . Autres fonctions
 . Fonctions et options à utiliser dans les clauses GROUP BY
 
 
 | 
  13.6 Recherche en texte intégral ( Full-text ) dans MySQL    
 
La recherche en texte intégral est effectuée par la fonction  
MATCH()
 .
MATCH (col1,col2,...) AGAINST (expr [IN BOOLEAN MODE | WITH QUERY EXPANSION])
 Depuis la version 3.23.23,  
MySQL
  propose l'indexation et la recherche sur 
l'ensemble d'un champ  
TEXT
  ( 
full-text
 ). Les index en texte intégral de 
 
MySQL
  sont des index de type  
FULLTEXT
 . Les index  
FULLTEXT
  sont 
utilisés avec les tables  
MyISAM
  et peuvent être 
créés depuis des colonnes de types  
CHAR
 ,  
VARCHAR
 ,
ou  
TEXT
  au moment de  
CREATE TABLE
  ou plus tard avec  
ALTER TABLE
 
ou  
CREATE INDEX
 . Pour les enregistrements les plus grands, il sera plus rapide
de charger les donnés dans une table qui n'a pas d'index  
FULLTEXT
 , 
et ensuite de créer l'index avec  
ALTER TABLE
  (ou  
CREATE
INDEX
 ). L'enregistrement de données dans une table qui a déjà 
des index  
FULLTEXT
  sera plus lent.
 
Les contraintes sur la recherche en texte intégral sont listées dans 
la section  Restrictions sur les recherches en texte intégral .
 La fonction  
MATCH()
  effectue la recherche d'une chaîne de caractères 
dans une liste de textes (et dans un groupe d'une ou plusieurs colonnes 
utilisées pour l'index   
FULLTEXT
 ). La chaîne recherchée 
est donnée en argument à  
AGAINST()
 . La recherche est sans 
distinguer les majuscules des minuscules. Pour chaque ligne de la table,
 
MATCH()
  retourne une valeur de pertinence, qui est une mesure de la 
ressemblance entre le chaîne recherchée et le texte de la ligne dans 
le colonne donnée dans la liste de  
MATCH()
 .Quand  
MATCH()
  est utilisé comme condition de  
WHERE
  
(voir l'exemple suivant) les lignes retournées sont automatiquement
organisées avec la pertinence la plus élevé 
en premier. La pertinence est un nombre décimal positif. La pertinence de 
zéro signifie qu'il n'y a pas de similarité. La pertinence 
est calculé en fonction du nombre de mots
dans la ligne, du nombre de mots uniques dans cette ligne, du nombre total de mots
dans la liste, et du nombre de documents (lignes) qui contiennent un 
mot en particulier.| 
mysql> CREATE TABLE articles (->   id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
 ->   title VARCHAR(200),
 ->   body TEXT,
 ->   FULLTEXT (title,body)
 -> );
 Query OK, 0 rows affected (0.00 sec)
 
 mysql> INSERT INTO articles VALUES
 -> (NULL,'MySQL Tutorial', 'DBMS stands for DataBase ...'),
 -> (NULL,'How To Use MySQL Efficiently', 'After you went through a ...'),
 -> (NULL,'Optimising MySQL','In this tutorial we will show ...'),
 -> (NULL,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
 -> (NULL,'MySQL vs. YourSQL', 'In the following database comparison ...'),
 -> (NULL,'MySQL Security', 'When configured properly, MySQL ...');
 Query OK, 6 rows affected (0.00 sec)
 Records: 6  Duplicates: 0  Warnings: 0
 
 mysql> SELECT * FROM articles
 ->          WHERE MATCH (title,body) AGAINST ('database');
 +----+-------------------+------------------------------------------+
 | id | title             | body                                     |
 +----+-------------------+------------------------------------------+
 |  5 | MySQL vs. YourSQL | In the following database comparison ... |
 |  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
 +----+-------------------+------------------------------------------+
 2 rows in set (0.00 sec)
 | 
 
Pour les recherches en texte intégral et en langage naturel, la technique impose
que les colonnes utilisées avec la fonction  
MATCH()
  doivent être les mêmes que
les colonnes utilisées dans un index  
FULLTEXT
 . Dans la requête précédente, notez
que les colonnes nommées dans la fonction  
MATCH()
  ( 
title
  et
 
body
 ) sont les mêmes que celles de la définition de la table 
 
article
  et son index  
FULLTEXT
 . Si vous voulez rechercher le titre
 
title
  ou le corps  
body
  séparément, vous devrez créer un index 
 
FULLTEXT
  pour chaque colonne.
Il est aussi possible d'exécuter une recherche en mode booléen. Ceci est 
décrit dans les sections  Opérateurs booléens de recherche  en texte intégral  et
 Recherches en texte intégral avec extension . 
L'exemple précédent est une illustration élémentaire 
qui montre comment on utilise la fonction  
MATCH()
 . Les lignes sont 
retournées par ordre décroissant de pertinence.
L'exemple suivant montre comment récupérer la valeur de pertinence
explicitement. Comme il n'y a pas de condition  
WHERE
  ni de condition  
ORDER BY
  
les lignes retournées ne sont pas ordonnées.
 L'exemple suivant est plus complexe. La requête retourne la valeur de
pertinence et organise les lignes par ordre décroissant de pertinence.
Pour obtenir ce résultat, il faut spécifier  
MATCH()
  deux 
fois. Cela ne cause pas de surcharge car l'optimiseur de  
MySQL
  remarquera que
les deux appels à  
MATCH()
  sont identiques et appellent le code 
de recherche sur texte intégral une seule fois.| 
mysql> SELECT id,MATCH (title,body) AGAINST ('Tutorial') FROM articles;+----+-----------------------------------------+
 | id | MATCH (title,body) AGAINST ('Tutorial') |
 +----+-----------------------------------------+
 |  1 |                        0.64840710366884 |
 |  2 |                                       0 |
 |  3 |                        0.66266459031789 |
 |  4 |                                       0 |
 |  5 |                                       0 |
 |  6 |                                       0 |
 +----+-----------------------------------------+
 6 rows in set (0.00 sec)
 | 
 MySQL
  utilise un filtre très simple pour séparer le texte en mots.
Un "mot" est n'importe quelle chaîne de caractères constituée de
lettres, chiffres,  
'''
  et  
'_'
 .  Tout "mot" présent dans la liste 
des mots à ignorés ou qui est trop court (3 caractères ou moins) 
est ignoré.| 
mysql> SELECT id, body, MATCH (title,body) AGAINST-> ('Security implications of running MySQL as root') AS score
 -> FROM articles WHERE MATCH (title,body) AGAINST
 -> ('Security implications of running MySQL as root');
 +----+-------------------------------------+-----------------+
 | id | body                                | score           |
 +----+-------------------------------------+-----------------+
 |  4 | 1. Never run mysqld as root. 2. ... | 1.5055546709332 |
 |  6 | When configured properly, MySQL ... |   1.31140957288 |
 +----+-------------------------------------+-----------------+
 2 rows in set (0.00 sec)
 | 
 
Un mot trop court est ignoré. La taille minimale pour un mot dans les
recherches est de 4 lettres.
Les mots de la liste sont ignorés. Un mot banni est par exemple 
`` 
the
 '' ou `` 
some
 '', ``un'' or ``les'' en français, qui sont considérés comme
trop communs pour avoir une valeur intrinsèque. Il y a une liste 
de mots bannis en anglais par défaut. 
La taille minimale des mots et la liste de mots à ignorer sont décrites
dans la section  Optimisation des recherches en texte intégral .
Tous les mots corrects de la liste et de la requête sont pondérés
en fonction de leur importance dans la liste ou la requête. De cette façon, 
un mot présent dans de nombreuses lignes aura un poids faible (et peut être 
même un poids nul), car il a peu d'importance dans cette requête particulière.
Au contraire, si le mot est rare, il recevra un poids fort. Le poids des mots sont alors
rassemblés pour calculer la pertinence de la ligne. 
Une telle technique fonctionne plus efficacement sur de grands volumes de données
(en fait, elle est optimisée pour cela). Avec les toutes petites tables, la distribution
des mots ne reflète par correctement leur valeur sémantique et ce modèle 
peut parfois produire des résultats étranges.
 La recherche du mot  
MySQL
  ne donne aucun résultat dans l'exemple précédent,
car il est présent dans plus de la moitié des lignes. Ainsi, il est considéré
comme un mot à ignorer (un mot avec une valeur sémantique nulle).  
C'est le comportement le plus optimal : un langage de requêtes ne doit pas retourner
chaque ligne d'une table de 1 Go.| 
mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL');Empty set (0.00 sec)
 | 
 
Un mot qui est trouvé dans la moitié des enregistrements d'une table n'est pas efficace
pour trouver les document appropriés. En fait, il trouvera sûrement beaucoup de documents
inappropriés à la recherche.
On sait tous que cela arrive souvent lorsqu'on recherche quelque chose sur internet en utilisant
un moteur de recherche. C'est en suivant ce raisonnement que ces lignes se sont vues attribuer
une valeur sémantique très basse dans  
ce cas particulier
 .
Le seuil de 50% a un impact significatif lorsque vous commencez à comprendre
comment fonctionne l'index : si vous créez une table et insérez une ou deux lignes,
chaque mot apparaîtra dans 50% des lignes. Résultat, la recherche ne trouvera rien.
Assurez-vous d'insérer au moins trois lignes, et même plus. Sommaire : |