V MySQL, MATCH()
funkce provádí fulltextové vyhledávání. Přijímá čárkami oddělený seznam sloupců tabulky, které se mají prohledávat.
Tabulka/y musí mít FULLTEXT
index, než proti nim budete moci provádět fulltextové vyhledávání (ačkoli logické dotazy proti MyISAM
vyhledávací index může fungovat – i když pomalu – i bez FULLTEXT
index).
Můžete vytvořit FULLTEXT
index při vytváření tabulky (pomocí CREATE TABLE
příkaz), nebo můžete použít ALTER TABLE
nebo CREATE INDEX
pokud tabulka již existuje.
Ve výchozím nastavení se při vyhledávání nerozlišuje malá a velká písmena. Chcete-li provést vyhledávání rozlišující malá a velká písmena, použijte pro indexované sloupce třídění rozlišující malá a velká písmena nebo binární řazení.
Syntaxe
Syntaxe pro MATCH()
funkce vypadá takto:
MATCH (col1,col2,...) AGAINST (expr [search_modifier])
Kde col1,col2,...
je čárkami oddělený seznam sloupců k vyhledávání a expr
je vstupní řetězec/výraz.
Volitelný search_modifier
argument umožňuje určit typ vyhledávání. Může to být kterákoli z následujících hodnot:
IN NATURAL LANGUAGE MODE
IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
IN BOOLEAN MODE
WITH QUERY EXPANSION
Výchozí režim je IN NATURAL LANGUAGE MODE
.
Příklad 1 – Základní použití
Zde je příklad použití této funkce:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('cool');
Výsledek:
+---------+--------------------+ | AlbumId | AlbumName | +---------+--------------------+ | 5 | Casualties of Cool | +---------+--------------------+
Zde je úplná tabulka, proti které byl spuštěn výše uvedený dotaz:
SELECT AlbumId, AlbumName FROM Albums;
Výsledek:
+---------+--------------------------+ | 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 | +---------+--------------------------+
Příklad 2 – Chyba:„Nelze najít FULLTEXTOVÝ index“
InnoDB
tabulky musí mít FULLTEXT
index, než vrátí výsledky z fulltextového vyhledávání. Pokud nemá FULLTEXT
index, pravděpodobně se zobrazí následující chyba:
ERROR 1191 (HY000): Can't find FULLTEXT index matching the column list
Pokud se zobrazí tato chyba, budete muset přidat FULLTEXT
index pro všechny sloupce, které se pokoušíte prohledat (viz další příklad).
Výjimkou může být situace, kdy spouštíte booleovský dotaz proti MyISAM
vyhledávací index.
Abychom byli konkrétnější, dokumentace MySQL pro booleovské fulltextové vyhledávání uvádí následující:
InnoDB
tabulky vyžadujíFULLTEXT
index ve všech sloupcíchMATCH()
výraz pro provádění booleovských dotazů. Booleovské dotazy protiMyISAM
vyhledávací index může fungovat i bezFULLTEXT
index, i když vyhledávání prováděné tímto způsobem by bylo poměrně pomalé.
Příklad 3 – Přidání FULLTEXTOVÉHO indexu do existující tabulky
Zde je příklad přidání FULLTEXT
index k existující tabulce:
ALTER TABLE Albums ADD FULLTEXT(AlbumName);
V tomto případě jsem indexoval obsah AlbumName
sloupec.
Chcete-li indexovat více sloupců, oddělte je čárkou (viz další příklad).
Příklad 4 – Prohledávání více sloupců
Pokud si myslíte, že budete muset prohledat více než jeden sloupec, budete muset vytvořit index, který bude obsahovat všechny sloupce, které se mají prohledávat. Chcete-li to provést, jednoduše zahrňte každý sloupec jako seznam oddělený čárkami.
Zde je příklad, kde přidám FULLTEXT
index na film
tabulky (která je součástí ukázkové databáze Sakila).
ALTER TABLE film ADD FULLTEXT(title, description);
V tomto případě indexuji obsah title
a description
sloupce.
Nyní, když jsme vytvořili FULLTEXT
index pro oba sloupce, můžeme proti nim provést fulltextové vyhledávání:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('vertigo');
Výsledek:
+-------------------+-----------------------------------------------------------------------------------------------------------+ | title | description | +-------------------+-----------------------------------------------------------------------------------------------------------+ | VERTIGO NORTHWEST | A Unbelieveable Display of a Mad Scientist And a Mad Scientist who must Outgun a Mad Cow in Ancient Japan | +-------------------+-----------------------------------------------------------------------------------------------------------+
Zde je další vyhledávání, kde se přesná klíčová fráze neshoduje, ale každé klíčové slovo v této frázi ano:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('Iron Maiden');
Výsledek:
+-------------+---------------------------------------------------------------------------------------------------------+ | 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 | +-------------+---------------------------------------------------------------------------------------------------------+
Pokud chcete, aby se shodovala pouze přesná fráze, umístěte kolem ní dvojité uvozovky:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Iron Maiden"');
Výsledek:
Empty set (0.00 sec)
V tomto případě žádný ze sloupců neobsahuje přesně tuto frázi.
Příklad 5 – Vrácení skóre relevance
Kdykoli použijete MATCH()
funkce, je každému řádku v tabulce přiřazena hodnota relevance. Jinými slovy, každý řádek získá skóre, které určuje, jak relevantní je pro hledaný výraz. Výsledky jsou poté seřazeny podle relevance (nejvyšší relevance jako první).
Hodnoty relevance jsou nezáporná čísla s plovoucí desetinnou čárkou. Nulová relevance znamená žádnou podobnost. Relevance se počítá na základě počtu slov v řádku (dokumentu), počtu jedinečných slov v řádku, celkového počtu slov ve sbírce a počtu řádků, které obsahují konkrétní slovo.
Chcete-li vrátit relevanci každého výsledku, jednoduše zahrňte MATCH()
funkce v seznamu sloupců k výběru.
Příklad:
SELECT MATCH(title, description) AGAINST('Iron Maiden') AS Relevance, title, description FROM film WHERE MATCH(title, description) AGAINST('Iron Maiden');
Výsledek:
+-----------+-------------+---------------------------------------------------------------------------------------------------------+ | 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 | +-----------+-------------+---------------------------------------------------------------------------------------------------------+
V tomto případě je skóre relevance pro oba řádky velmi vysoké.
Zde je další, kde je relevance nižší:
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;
Výsledek:
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | 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 | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Všimněte si, že sada výsledků by byla mnohem větší, kdybych nepoužil LIMIT 15
omezit počet výsledků na 15.
Příklad 6 – Vraťte pouze výsledky nad určitým skóre relevance
Předchozí příklad můžeme posunout o krok dále a vyfiltrovat pouze ty výsledky s určitým skóre relevance. V tomto případě specifikuji, že skóre relevance musí být vyšší než 2.
Buďte opatrní, když to děláte. Jak je vidět výše, hodnoty relevance mohou být velmi vysoké nebo velmi nízké v závislosti na faktorech, jako je množství textu ve sloupci, kolik dalších řádků odpovídá hledanému výrazu atd.
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;
Výsledek:
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | 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 | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Příklad 7 – Zahrnout výsledky nulové relevance
Zde je příklad uvedení hodnot relevance pro každý řádek, i když je hodnota relevance nulová. Můžeme to udělat tak, že nepoužijeme MATCH()
funkce v WHERE
doložka.
V tomto příkladu ve skutečnosti nepoužívám WHERE
doložka. Používám pouze LIMIT
klauzule k omezení počtu výsledků.
SELECT MATCH(title, description) AGAINST('Scientist') AS Relevance, title, description FROM film LIMIT 15;
Výsledek:
+-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+ | 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 | +-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+
Příklad 8 – Booleovský režim
MySQL nám umožňuje spouštět fulltextové vyhledávání v booleovském režimu. Chcete-li to provést, přidejte IN BOOLEAN MODE
modifikátor vašeho dotazu.
Booleovský režim vám umožňuje používat operátory jako +
a -
určit, zda určité slovo nebo fráze musí nebo nesmí být přítomno.
V následujícím příkladu před každým slovem uvedu znaménko plus (+
) označující, že musí být přítomna obě slova.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('+Saga +Moose' IN BOOLEAN MODE) LIMIT 3;
Výsledek:
+------------------------+---------------------------------------------------------------------------------------------+ | 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 | +------------------------+---------------------------------------------------------------------------------------------+
V dalším příkladu změním jedno ze znamének plus na znaménko mínus (-
). To znamená, že pouze ty řádky, které obsahují slovo Saga
budou vráceny, ale pouze pokud nebudou obsahují také Moose
:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('+Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Výsledek:
+------------------+-------------------------------------------------------------------------------------------------+ | 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 | +------------------+-------------------------------------------------------------------------------------------------+
Znaménko minus se používá k vyloučení výsledků, které by jinak byly vráceny. Pokud jsou tedy všechna naše hledaná slova uvedena před znaménkem mínus, vrátí se prázdná množina.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('-Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Výsledek:
Empty set (0.00 sec)
Existuje mnohem více operátorů, které lze použít s booleovským vyhledáváním, například ~
, <
, >
, *
, a více. Podrobnější informace o používání booleovského režimu najdete v dokumentaci MySQL pro booleovské fulltextové vyhledávání.
Příklad 9 – S rozšířením dotazu naslepo
Můžete použít WITH QUERY EXPANSION
nebo IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
modifikátory pro provádění slepého rozšíření dotazu. To může být užitečné v případech, kdy je hledaná fráze velmi krátká a kde by vrácené výsledky mohly být příliš úzké (a tím vylučují potenciálně relevantní dokumenty).
Rozšíření dotazu může rozšířit vyhledávání tím, že vrátí řádky, které by jinak nebyly vráceny. Konkrétně, pokud neodpovídající řádek obsahuje slova, která jsou také obsažena v odpovídajícím řádku, může se tento neodpovídající řádek stát odpovídajícím řádkem. Jinými slovy, neodpovídající řádek lze stále vrátit, jednoduše proto, že sdílí jiná slova se shodným řádkem.
Jako ukázku uvádíme normální vyhledávání bez rozšíření dotazu:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' IN NATURAL LANGUAGE MODE);
Výsledek:
+---------+------------+ | AlbumId | AlbumName | +---------+------------+ | 13 | Blue Night | +---------+------------+
Výslovně jsem uvedl IN NATURAL LANGUAGE MODE
ale toto je výchozí režim, takže pokud bych se tak rozhodl, mohl jsem tento modifikátor vynechat.
A zde je stejné vyhledávání s rozšíření dotazu:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' WITH QUERY EXPANSION);
Výsledek:
+---------+-----------------+ | AlbumId | AlbumName | +---------+-----------------+ | 13 | Blue Night | | 19 | All Night Wrong | +---------+-----------------+
V tomto případě jsou vráceny dva výsledky. Všimněte si, že druhý výsledek neobsahuje hledaný výraz (blue
). Obsahuje však slovo Night
což je shodou okolností také v prvním výsledku. Rozšířený dotaz to tedy považuje za dostatečně dobré, aby se shodoval.
Názvy alb pravděpodobně nejsou příliš dobrým příkladem použití pro režim rozšíření dotazu. Lepším případem použití může být vyhledávání řekněme databáze , kde rozšířený dotaz může také vrátit dokumenty, které obsahují názvy jako MySQL , Oracle atd., i když neobsahují frázi databáze .
Zde je další příklad. Tento příklad však používá dvojité uvozovky k určení, že by měl být přítomen celý hledaný výraz.
Pokud provedeme vyhledávání bez rozšíření dotazu:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"') LIMIT 3;
Výsledek:
+------------------+--------------------------------------------------------------------------------------------------+ | title | description | +------------------+--------------------------------------------------------------------------------------------------+ | ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies | +------------------+--------------------------------------------------------------------------------------------------+
Vrátí se pouze jeden výsledek (je to jediný výsledek, který obsahuje celou frázi, přesně tak, jak byla napsána).
Pokud ale použijeme rozšíření dotazu naslepo, stane se toto:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION) LIMIT 3;
Výsledek:
+--------------------+------------------------------------------------------------------------------------------------------+ | 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 | +--------------------+------------------------------------------------------------------------------------------------------+
První řádek je stejný, jako když jsme rozšíření dotazu nepoužili. Dotaz však poté přejde a vrátí řádky, které obsahují pouze části našeho hledaného výrazu. Tento výsledek je omezen na tři pouze proto, že jsem použil LIMIT 3
. Skutečné výsledky jsou mnohem lepší:
SELECT COUNT(*) FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION);
Výsledek:
+----------+ | COUNT(*) | +----------+ | 1000 | +----------+
Je docela možné, že mnohé z těchto výsledků jsou pro hledaný výraz zcela irelevantní. Rozšíření dotazu naslepo proto obvykle funguje nejlépe pro kratší vyhledávací dotazy.
Další informace o používání rozšíření dotazů naslepo najdete v dokumentaci MySQL:Full-Text Searches with Query Expansion.