Dans MySQL, le MATCH()
La fonction effectue une recherche plein texte. Il accepte une liste de colonnes de table séparées par des virgules à rechercher.
La ou les tables doivent avoir un FULLTEXT
index avant de pouvoir effectuer une recherche en texte intégral sur eux (bien que les requêtes booléennes sur un MyISAM
l'index de recherche peut fonctionner - bien que lentement - même sans FULLTEXT
indice).
Vous pouvez créer un FULLTEXT
index lors de la création de la table (en utilisant le CREATE TABLE
déclaration), ou vous pouvez utiliser la ALTER TABLE
ou l'instruction CREATE INDEX
déclaration si la table existe déjà.
Par défaut, la recherche est insensible à la casse. Pour effectuer une recherche sensible à la casse, utilisez un classement binaire ou sensible à la casse pour les colonnes indexées.
Syntaxe
La syntaxe de MATCH()
la fonction se présente comme suit :
MATCH (col1,col2,...) AGAINST (expr [search_modifier])
Où col1,col2,...
est la liste des colonnes à rechercher séparées par des virgules, et expr
est la chaîne/expression d'entrée.
Le search_modifier
facultatif L'argument vous permet de spécifier le type de recherche. Il peut s'agir de l'une des valeurs suivantes :
IN NATURAL LANGUAGE MODE
IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
IN BOOLEAN MODE
WITH QUERY EXPANSION
Le mode par défaut est IN NATURAL LANGUAGE MODE
.
Exemple 1 - Utilisation de base
Voici un exemple d'utilisation de cette fonction :
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('cool');
Résultat :
+---------+--------------------+ | AlbumId | AlbumName | +---------+--------------------+ | 5 | Casualties of Cool | +---------+--------------------+
Voici la table complète sur laquelle la requête ci-dessus a été exécutée :
SELECT AlbumId, AlbumName FROM Albums;
Résultat :
+---------+--------------------------+ | AlbumId | AlbumName | +---------+--------------------------+ | 1 | Powerslave | | 2 | Powerage | | 3 | Singing Down the Lane | | 4 | Ziltoid the Omniscient | | 5 | Casualties of Cool | | 6 | Epicloud | | 7 | Somewhere in Time | | 8 | Piece of Mind | | 9 | Killers | | 10 | No Prayer for the Dying | | 11 | No Sound Without Silence | | 12 | Big Swing Face | | 13 | Blue Night | | 14 | Eternity | | 15 | Scandinavia | | 16 | Long Lost Suitcase | | 17 | Praise and Blame | | 18 | Along Came Jones | | 19 | All Night Wrong | | 20 | The Sixteen Men of Tain | +---------+--------------------------+
Exemple 2 – Erreur :"Impossible de trouver l'index FULLTEXT"
InnoDB
les tables doivent avoir un FULLTEXT
index avant de renvoyer les résultats d'une recherche en texte intégral. S'il n'a pas de FULLTEXT
index, vous obtiendrez probablement l'erreur suivante :
ERROR 1191 (HY000): Can't find FULLTEXT index matching the column list
Si vous obtenez cette erreur, vous devrez ajouter un FULLTEXT
index pour toutes les colonnes que vous essayez de rechercher (voir l'exemple suivant).
L'exception à cela pourrait être si vous exécutez une requête booléenne sur un MyISAM
indice de recherche.
Pour être plus précis, la documentation MySQL pour les recherches booléennes en texte intégral indique ce qui suit :
InnoDB
les tables nécessitent unFULLTEXT
index sur toutes les colonnes duMATCH()
expression pour effectuer des requêtes booléennes. Requêtes booléennes sur unMyISAM
l'index de recherche peut fonctionner même sansFULLTEXT
index, même si une recherche exécutée de cette manière serait assez lente.
Exemple 3 – Ajout d'un index FULLTEXT à une table existante
Voici un exemple d'ajout d'un FULLTEXT
indexer vers une table existante :
ALTER TABLE Albums ADD FULLTEXT(AlbumName);
Dans ce cas, j'ai indexé le contenu de l'AlbumName
colonne.
Pour indexer plusieurs colonnes, séparez-les par une virgule (voir l'exemple suivant).
Exemple 4 - Recherche de plusieurs colonnes
Si vous pensez que vous devrez rechercher plus d'une colonne, vous devrez créer un index qui inclut toutes les colonnes à rechercher. Pour ce faire, incluez simplement chaque colonne sous forme de liste séparée par des virgules.
Voici un exemple où j'ajoute un FULLTEXT
index du film
table (qui fait partie de l'exemple de base de données Sakila).
ALTER TABLE film ADD FULLTEXT(title, description);
Dans ce cas, j'indexe le contenu du title
et description
colonnes.
Maintenant que nous avons créé un FULLTEXT
index pour les deux colonnes, nous pouvons effectuer une recherche en texte intégral sur celles-ci :
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('vertigo');
Résultat :
+-------------------+-----------------------------------------------------------------------------------------------------------+ | title | description | +-------------------+-----------------------------------------------------------------------------------------------------------+ | VERTIGO NORTHWEST | A Unbelieveable Display of a Mad Scientist And a Mad Scientist who must Outgun a Mad Cow in Ancient Japan | +-------------------+-----------------------------------------------------------------------------------------------------------+
Voici une autre recherche, où la phrase clé exacte ne correspond pas, mais chaque mot clé de cette phrase correspond :
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('Iron Maiden');
Résultat :
+-------------+---------------------------------------------------------------------------------------------------------+ | title | description | +-------------+---------------------------------------------------------------------------------------------------------+ | IRON MOON | A Fast-Paced Documentary of a Mad Cow And a Boy who must Pursue a Dentist in A Baloon | | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MySQL Convention | +-------------+---------------------------------------------------------------------------------------------------------+
Si vous souhaitez que seule la phrase exacte corresponde, placez-la entre guillemets :
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Iron Maiden"');
Résultat :
Empty set (0.00 sec)
Dans ce cas, aucune des colonnes ne contient cette expression exacte.
Exemple 5 - Renvoyer le score de pertinence
Chaque fois que vous utilisez le MATCH()
fonction, chaque ligne du tableau se voit attribuer une valeur de pertinence. En d'autres termes, chaque ligne obtient un score qui détermine sa pertinence par rapport au terme de recherche. Les résultats sont ensuite classés par pertinence (la pertinence la plus élevée en premier).
Les valeurs de pertinence sont des nombres à virgule flottante non négatifs. Aucune pertinence signifie aucune similitude. La pertinence est calculée en fonction du nombre de mots dans la ligne (document), du nombre de mots uniques dans la ligne, du nombre total de mots dans la collection et du nombre de lignes contenant un mot particulier.
Pour retourner la pertinence de chaque résultat, incluez simplement le MATCH()
fonction dans votre liste de colonnes à sélectionner.
Exemple :
SELECT MATCH(title, description) AGAINST('Iron Maiden') AS Relevance, title, description FROM film WHERE MATCH(title, description) AGAINST('Iron Maiden');
Résultat :
+-----------+-------------+---------------------------------------------------------------------------------------------------------+ | Relevance | title | description | +-----------+-------------+---------------------------------------------------------------------------------------------------------+ | 9 | IRON MOON | A Fast-Paced Documentary of a Mad Cow And a Boy who must Pursue a Dentist in A Baloon | | 9 | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MySQL Convention | +-----------+-------------+---------------------------------------------------------------------------------------------------------+
Dans ce cas, le score de pertinence est très élevé pour les deux lignes.
En voici une autre dont la pertinence est moindre :
SELECT MATCH(title, description) AGAINST('Saga of a Moose') AS Relevance, title, description FROM film WHERE MATCH(title, description) AGAINST('Saga of a Moose') LIMIT 15;
Résultat :
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | Relevance | title | description | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | 2.4431142807006836 | CAPER MOTIONS | A Fateful Saga of a Moose And a Car who must Pursue a Woman in A MySQL Convention | | 2.4431142807006836 | DATE SPEED | A Touching Saga of a Composer And a Moose who must Discover a Dentist in A MySQL Convention | | 2.4431142807006836 | DELIVERANCE MULHOLLAND | A Astounding Saga of a Monkey And a Moose who must Conquer a Butler in A Shark Tank | | 2.4431142807006836 | FLASH WARS | A Astounding Saga of a Moose And a Pastry Chef who must Chase a Student in The Gulf of Mexico | | 2.4431142807006836 | HAROLD FRENCH | A Stunning Saga of a Sumo Wrestler And a Student who must Outrace a Moose in The Sahara Desert | | 2.4431142807006836 | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MySQL Convention | | 2.4431142807006836 | SHANE DARKNESS | A Action-Packed Saga of a Moose And a Lumberjack who must Find a Woman in Berlin | | 2.4431142807006836 | SLEEPLESS MONSOON | A Amazing Saga of a Moose And a Pastry Chef who must Escape a Butler in Australia | | 2.4431142807006836 | WAKE JAWS | A Beautiful Saga of a Feminist And a Composer who must Challenge a Moose in Berlin | | 2.4431142807006836 | WONKA SEA | A Brilliant Saga of a Boat And a Mad Scientist who must Meet a Moose in Ancient India | | 1.2399028539657593 | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat | | 1.2399028539657593 | ALASKA PHANTOM | A Fanciful Saga of a Hunter And a Pastry Chef who must Vanquish a Boy in Australia | | 1.2399028539657593 | ARMY FLINTSTONES | A Boring Saga of a Database Administrator And a Womanizer who must Battle a Waitress in Nigeria | | 1.2399028539657593 | BEAR GRACELAND | A Astounding Saga of a Dog And a Boy who must Kill a Teacher in The First Manned Space Station | | 1.2399028539657593 | BERETS AGENT | A Taut Saga of a Crocodile And a Boy who must Overcome a Technical Writer in Ancient China | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Notez que le jeu de résultats aurait été beaucoup plus grand si je n'avais pas utilisé LIMIT 15
pour limiter le nombre de résultats à 15.
Exemple 6 :ne renvoient que les résultats supérieurs à un certain score de pertinence
Nous pouvons pousser l'exemple précédent un peu plus loin et filtrer uniquement les résultats avec un certain score de pertinence. Dans ce cas je précise que le score de pertinence doit être supérieur à 2.
Soyez prudent lorsque vous faites cela cependant. Comme indiqué ci-dessus, les valeurs de pertinence peuvent être très élevées ou très faibles, en fonction de facteurs tels que la quantité de texte dans la colonne, le nombre d'autres lignes correspondant au terme de recherche, etc.
SELECT MATCH(title, description) AGAINST('Saga of a Moose') AS Relevance, title, description FROM film WHERE MATCH(title, description) AGAINST('Saga of a Moose') > 2;
Résultat :
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | Relevance | title | description | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | 2.4431142807006836 | CAPER MOTIONS | A Fateful Saga of a Moose And a Car who must Pursue a Woman in A MySQL Convention | | 2.4431142807006836 | DATE SPEED | A Touching Saga of a Composer And a Moose who must Discover a Dentist in A MySQL Convention | | 2.4431142807006836 | DELIVERANCE MULHOLLAND | A Astounding Saga of a Monkey And a Moose who must Conquer a Butler in A Shark Tank | | 2.4431142807006836 | FLASH WARS | A Astounding Saga of a Moose And a Pastry Chef who must Chase a Student in The Gulf of Mexico | | 2.4431142807006836 | HAROLD FRENCH | A Stunning Saga of a Sumo Wrestler And a Student who must Outrace a Moose in The Sahara Desert | | 2.4431142807006836 | MAIDEN HOME | A Lacklusture Saga of a Moose And a Teacher who must Kill a Forensic Psychologist in A MySQL Convention | | 2.4431142807006836 | SHANE DARKNESS | A Action-Packed Saga of a Moose And a Lumberjack who must Find a Woman in Berlin | | 2.4431142807006836 | SLEEPLESS MONSOON | A Amazing Saga of a Moose And a Pastry Chef who must Escape a Butler in Australia | | 2.4431142807006836 | WAKE JAWS | A Beautiful Saga of a Feminist And a Composer who must Challenge a Moose in Berlin | | 2.4431142807006836 | WONKA SEA | A Brilliant Saga of a Boat And a Mad Scientist who must Meet a Moose in Ancient India | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Exemple 7 - Inclure des résultats sans pertinence
Voici un exemple de liste des valeurs de pertinence pour chaque ligne, même si la valeur de pertinence est zéro. Nous pouvons le faire en n'utilisant pas le MATCH()
fonction dans le WHERE
clause.
Dans cet exemple, je n'utilise pas réellement de WHERE
clause. Je n'utilise qu'un LIMIT
clause pour limiter le nombre de résultats.
SELECT MATCH(title, description) AGAINST('Scientist') AS Relevance, title, description FROM film LIMIT 15;
Résultat :
+-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+ | Relevance | title | description | +-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+ | 1.026631474494934 | ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies | | 0 | ACE GOLDFINGER | A Astounding Epistle of a Database Administrator And a Explorer who must Find a Car in Ancient China | | 0 | ADAPTATION HOLES | A Astounding Reflection of a Lumberjack And a Car who must Sink a Lumberjack in A Baloon Factory | | 0 | AFFAIR PREJUDICE | A Fanciful Documentary of a Frisbee And a Lumberjack who must Chase a Monkey in A Shark Tank | | 0 | AFRICAN EGG | A Fast-Paced Documentary of a Pastry Chef And a Dentist who must Pursue a Forensic Psychologist in The Gulf of Mexico | | 0 | AGENT TRUMAN | A Intrepid Panorama of a Robot And a Boy who must Escape a Sumo Wrestler in Ancient China | | 0 | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat | | 0 | AIRPORT POLLOCK | A Epic Tale of a Moose And a Girl who must Confront a Monkey in Ancient India | | 2.053262948989868 | ALABAMA DEVIL | A Thoughtful Panorama of a Database Administrator And a Mad Scientist who must Outgun a Mad Scientist in A Jet Boat | | 0 | ALADDIN CALENDAR | A Action-Packed Tale of a Man And a Lumberjack who must Reach a Feminist in Ancient China | | 0 | ALAMO VIDEOTAPE | A Boring Epistle of a Butler And a Cat who must Fight a Pastry Chef in A MySQL Convention | | 0 | ALASKA PHANTOM | A Fanciful Saga of a Hunter And a Pastry Chef who must Vanquish a Boy in Australia | | 0 | ALI FOREVER | A Action-Packed Drama of a Dentist And a Crocodile who must Battle a Feminist in The Canadian Rockies | | 0 | ALICE FANTASIA | A Emotional Drama of a A Shark And a Database Administrator who must Vanquish a Pioneer in Soviet Georgia | | 1.026631474494934 | ALIEN CENTER | A Brilliant Drama of a Cat And a Mad Scientist who must Battle a Feminist in A MySQL Convention | +-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+
Exemple 8 – Mode booléen
MySQL nous permet d'effectuer des recherches en texte intégral en mode booléen. Pour cela, ajoutez le IN BOOLEAN MODE
modificateur à votre requête.
Le mode booléen vous permet d'utiliser des opérateurs tels que +
et -
pour spécifier si un mot ou une phrase particulière doit ou ne doit pas être présent.
Dans l'exemple suivant, je préfixe chaque mot avec un signe plus (+
) pour indiquer que les deux mots doivent être présents.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('+Saga +Moose' IN BOOLEAN MODE) LIMIT 3;
Résultat :
+------------------------+---------------------------------------------------------------------------------------------+ | title | description | +------------------------+---------------------------------------------------------------------------------------------+ | CAPER MOTIONS | A Fateful Saga of a Moose And a Car who must Pursue a Woman in A MySQL Convention | | DATE SPEED | A Touching Saga of a Composer And a Moose who must Discover a Dentist in A MySQL Convention | | DELIVERANCE MULHOLLAND | A Astounding Saga of a Monkey And a Moose who must Conquer a Butler in A Shark Tank | +------------------------+---------------------------------------------------------------------------------------------+
Dans l'exemple suivant, je change l'un des signes plus en signe moins (-
). Cela signifie que seules les lignes contenant le mot Saga
seront retournés, mais seulement s'ils ne le font pas contient également Moose
:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('+Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Résultat :
+------------------+-------------------------------------------------------------------------------------------------+ | title | description | +------------------+-------------------------------------------------------------------------------------------------+ | AIRPLANE SIERRA | A Touching Saga of a Hunter And a Butler who must Discover a Butler in A Jet Boat | | ALASKA PHANTOM | A Fanciful Saga of a Hunter And a Pastry Chef who must Vanquish a Boy in Australia | | ARMY FLINTSTONES | A Boring Saga of a Database Administrator And a Womanizer who must Battle a Waitress in Nigeria | +------------------+-------------------------------------------------------------------------------------------------+
Le signe moins est utilisé pour exclure les résultats qui seraient autrement renvoyés. Par conséquent, si tous nos mots de recherche sont précédés d'un signe moins, un ensemble vide est renvoyé.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('-Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Résultat :
Empty set (0.00 sec)
Il existe de nombreux autres opérateurs pouvant être utilisés avec des recherches booléennes, tels que ~
, <
, >
, *
, et plus. Pour plus d'informations sur l'utilisation du mode booléen, consultez la documentation MySQL pour les recherches booléennes en texte intégral.
Exemple 9 – Avec l'extension Blind Query
Vous pouvez utiliser le WITH QUERY EXPANSION
ou le IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
modificateurs pour effectuer une expansion de requête aveugle. Cela peut être utile lorsque la phrase de recherche est très courte et que les résultats renvoyés peuvent être trop étroits (excluant ainsi les documents potentiellement pertinents).
L'extension de la requête peut élargir la recherche en renvoyant des lignes qui, autrement, ne seraient pas renvoyées. En particulier, si une ligne non concordante contient des mots qui sont également contenus dans une ligne concordante, cette ligne non concordante peut devenir une ligne concordante. En d'autres termes, une ligne non correspondante peut toujours être renvoyée, simplement parce qu'elle partage d'autres mots avec une ligne correspondante.
Pour démontrer, voici une recherche normale sans extension de requête :
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' IN NATURAL LANGUAGE MODE);
Résultat :
+---------+------------+ | AlbumId | AlbumName | +---------+------------+ | 13 | Blue Night | +---------+------------+
J'ai explicitement indiqué IN NATURAL LANGUAGE MODE
mais c'est le mode par défaut, donc j'aurais aussi pu omettre ce modificateur si j'avais choisi de le faire.
Et voici la même recherche avec extension de requête :
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' WITH QUERY EXPANSION);
Résultat :
+---------+-----------------+ | AlbumId | AlbumName | +---------+-----------------+ | 13 | Blue Night | | 19 | All Night Wrong | +---------+-----------------+
Dans ce cas, deux résultats sont renvoyés. Remarquez que le deuxième résultat ne contient pas la phrase de recherche (blue
). Mais il contient le mot Night
qui se trouve également dans le premier résultat. Ainsi, la requête étendue considère que cela est suffisant pour être une correspondance.
Les noms d'album ne sont probablement pas un très bon cas d'utilisation pour le mode d'extension de requête. Un meilleur cas d'utilisation pourrait être une recherche de, par exemple, base de données , où une requête étendue peut également renvoyer des documents contenant des noms tels que MySQL , Oracle , etc même s'ils ne contiennent pas la phrase database .
Voici un autre exemple. Cependant, cet exemple utilise des guillemets doubles pour spécifier que le terme de recherche complet doit être présent.
Si nous faisons la recherche sans extension de requête :
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"') LIMIT 3;
Résultat :
+------------------+--------------------------------------------------------------------------------------------------+ | title | description | +------------------+--------------------------------------------------------------------------------------------------+ | ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies | +------------------+--------------------------------------------------------------------------------------------------+
Un seul résultat est renvoyé (c'est le seul résultat qui contient la phrase entière, exactement telle qu'elle a été saisie).
Mais si nous utilisons l'extension de requête aveugle, voici ce qui se passe :
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION) LIMIT 3;
Résultat :
+--------------------+------------------------------------------------------------------------------------------------------+ | title | description | +--------------------+------------------------------------------------------------------------------------------------------+ | ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies | | DINOSAUR SECRETARY | A Action-Packed Drama of a Feminist And a Girl who must Reach a Robot in The Canadian Rockies | | VICTORY ACADEMY | A Insightful Epistle of a Mad Scientist And a Explorer who must Challenge a Cat in The Sahara Desert | +--------------------+------------------------------------------------------------------------------------------------------+
La première ligne est la même que lorsque nous n'utilisions pas l'extension de requête. Cependant, la requête va ensuite et renvoie des lignes qui ne contiennent que des parties de notre terme de recherche. Ce résultat est limité à trois uniquement car j'ai utilisé LIMIT 3
. Les résultats réels sont bien meilleurs :
SELECT COUNT(*) FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION);
Résultat :
+----------+ | COUNT(*) | +----------+ | 1000 | +----------+
Il est tout à fait possible que bon nombre de ces résultats soient totalement sans rapport avec le terme de recherche. Par conséquent, l'expansion aveugle des requêtes fonctionne généralement mieux pour les termes de recherche plus courts.
Pour plus d'informations sur l'utilisation de l'extension de requête aveugle, consultez la documentation MySQL :Recherches en texte intégral avec extension de requête.