[+/-]
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 Section 12.6.3, « Restrictions avec la recherche en texte intégral ».
La recherche en texte intégral est effectuée par la fonction
MATCH()
.
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)
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.
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 Section 12.6.1, « Booléens de recherches en texte intégral » et Section 12.6.2, « Recherche en texte intégral avec extension de requête ».
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.
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)
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, 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)
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é.
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 Section 12.6.4, « Paramétrage précis de la recherche en text intégral de MySQL ».
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.
mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL');
Empty set (0.00 sec)
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.
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.
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.