I MySQL, MATCH()
funktionen utför en fulltextsökning. Den accepterar en kommaseparerad lista med tabellkolumner som ska sökas i.
Tabellen/tabellerna måste ha en FULLTEXT
indexera innan du kan göra en fulltextsökning mot dem (även om booleska frågor mot en MyISAM
sökindex kan fungera – om än långsamt – även utan en FULLTEXT
index).
Du kan skapa en FULLTEXT
index när du skapar tabellen (med hjälp av CREATE TABLE
uttalande), eller så kan du använda ALTER TABLE
eller CREATE INDEX
uttalande om tabellen redan finns.
Som standard är sökningen skiftlägesokänslig. För att utföra en skiftlägeskänslig sökning, använd en skiftlägeskänslig eller binär sammanställning för de indexerade kolumnerna.
Syntax
Syntaxen för MATCH()
funktionen går så här:
MATCH (col1,col2,...) AGAINST (expr [search_modifier])
Där col1,col2,...
är den kommaseparerade listan över kolumner att söka i, och expr
är inmatningssträngen/uttrycket.
Den valfria search_modifier
argument låter dig ange söktypen. Det kan vara något av följande värden:
I NATURLIGT SPRÅKSLÄGE
I NATURLIGT SPRÅKLÄGE MED FRÄGEEXPANSION
I BOOLENSK LÄGE
Med QUERY EXPANSION
Standardläget är I NATURAL LANGUAGE LÄGE
.
Exempel 1 – Grundläggande användning
Här är ett exempel på hur du använder den här funktionen:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('cool');
Resultat:
+---------+--------------------+ | AlbumId | AlbumName | +---------+--------------------+ | 5 | Casualties of Cool | +---------+--------------------+
Här är den fullständiga tabellen som ovanstående fråga kördes mot:
SELECT AlbumId, AlbumName FROM Albums;
Resultat:
+---------+--------------------------+ | 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 | +---------+--------------------------+
Exempel 2 – Fel:"Kan inte hitta FULLTEXT-index"
InnoDB
tabeller måste ha en FULLTEXT
indexera innan det returnerar resultat från en fulltextsökning. Om den inte har en FULLTEXT
index kommer du troligen att få följande felmeddelande:
ERROR 1191 (HY000): Can't find FULLTEXT index matching the column list
Om du får det felet måste du lägga till en FULLTEXT
index för alla kolumner som du försöker söka i (se nästa exempel).
Undantaget från detta kan vara om du kör en boolesk fråga mot en MyISAM
sökindex.
För att vara mer specifik anger MySQL-dokumentationen för booleska fulltextsökningar följande:
InnoDB
tabeller kräver enFULLTEXT
index på alla kolumner iMATCH()
uttryck för att utföra booleska frågor. Booleska frågor mot enMyISAM
sökindex kan fungera även utan enFULLTEXT
index, även om en sökning som utförs på detta sätt skulle vara ganska långsam.
Exempel 3 – Lägga till ett FULLTEXT-index till en befintlig tabell
Här är ett exempel på hur du lägger till en FULLTEXT
indexera till en befintlig tabell:
ALTER TABLE Albums ADD FULLTEXT(AlbumName);
I det här fallet indexerade jag innehållet i AlbumName
kolumn.
För att indexera flera kolumner, separera dem med ett kommatecken (se nästa exempel).
Exempel 4 – Söka i flera kolumner
Om du tror att du behöver söka i mer än en kolumn måste du skapa ett index som inkluderar alla kolumner som ska sökas i. För att göra detta, inkludera helt enkelt varje kolumn som en kommaseparerad lista.
Här är ett exempel där jag lägger till en FULLTEXT
indexera till filmen
tabell (som är en del av Sakila exempeldatabas).
ALTER TABLE film ADD FULLTEXT(title, description);
I det här fallet indexerar jag innehållet i titeln
och beskrivning
kolumner.
Nu när vi har skapat en FULLTEXT
index för båda kolumnerna kan vi göra en fulltextsökning mot dem:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('vertigo');
Resultat:
+-------------------+-----------------------------------------------------------------------------------------------------------+ | title | description | +-------------------+-----------------------------------------------------------------------------------------------------------+ | VERTIGO NORTHWEST | A Unbelieveable Display of a Mad Scientist And a Mad Scientist who must Outgun a Mad Cow in Ancient Japan | +-------------------+-----------------------------------------------------------------------------------------------------------+
Här är en annan sökning, där den exakta nyckelfrasen inte matchar, men varje sökord i den frasen gör det:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('Iron Maiden');
Resultat:
+-------------+---------------------------------------------------------------------------------------------------------+ | 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 | +-------------+---------------------------------------------------------------------------------------------------------+
Om du bara vill att den exakta frasen ska matcha, placera dubbla citattecken runt den:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Iron Maiden"');
Resultat:
Empty set (0.00 sec)
I det här fallet innehåller ingen av kolumnerna den exakta frasen.
Exempel 5 – Returnera relevanspoängen
När du använder MATCH()
funktion tilldelas varje rad i tabellen ett relevansvärde. Med andra ord får varje rad en poäng som avgör hur relevant den är för söktermen. Resultaten sorteras sedan efter relevans (högsta relevans först).
Relevansvärden är icke-negativa flyttal. Noll relevans betyder ingen likhet. Relevans beräknas baserat på antalet ord i raden (dokumentet), antalet unika ord i raden, det totala antalet ord i samlingen och antalet rader som innehåller ett visst ord.
För att returnera relevansen för varje resultat, inkludera helt enkelt MATCH()
funktion i din lista över kolumner för att välja.
Exempel:
SELECT MATCH(title, description) AGAINST('Iron Maiden') AS Relevance, title, description FROM film WHERE MATCH(title, description) AGAINST('Iron Maiden');
Resultat:
+-----------+-------------+---------------------------------------------------------------------------------------------------------+ | 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 | +-----------+-------------+---------------------------------------------------------------------------------------------------------+
I det här fallet är relevanspoängen mycket hög för båda raderna.
Här är en annan där relevansen är lägre:
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;
Resultat:
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | 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 | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Observera att resultatuppsättningen skulle ha varit mycket större om jag inte hade använt LIMIT 15
för att begränsa antalet resultat till 15.
Exempel 6 – Returnerar endast resultat över ett visst relevanspoäng
Vi kan ta det föregående exemplet ett steg längre och filtrera bort endast de resultat med en viss relevanspoäng. I det här fallet specificerar jag att relevanspoängen måste vara högre än 2.
Var dock försiktig när du gör detta. Som framgår ovan kan relevansvärdena vara mycket höga eller mycket låga, beroende på faktorer som hur mycket text som finns i kolumnen, hur många andra rader som matchar söktermen, 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;
Resultat:
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | 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 | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Exempel 7 – Inkludera nollrelevansresultat
Här är ett exempel på att lista ut relevansvärdena för varje rad, även om relevansvärdet är noll. Vi kan göra detta genom att inte använda MATCH()
funktion i WHERE
klausul.
I det här exemplet använder jag faktiskt inte en WHERE
klausul. Jag använder bara en LIMIT
klausul för att begränsa antalet resultat.
SELECT MATCH(title, description) AGAINST('Scientist') AS Relevance, title, description FROM film LIMIT 15;
Resultat:
+-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+ | 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 | +-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+
Exempel 8 – Boolean Mode
MySQL låter oss köra fulltextsökningar i booleskt läge. För att göra detta, lägg till I BOOLENSK LÄGE
modifierare till din fråga.
Booleskt läge låter dig använda operatorer som +
och -
för att ange om ett visst ord eller en viss fras måste eller inte får finnas.
I följande exempel prefixar jag varje ord med ett plustecken (+
) för att indikera att båda orden måste finnas.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('+Saga +Moose' IN BOOLEAN MODE) LIMIT 3;
Resultat:
+------------------------+---------------------------------------------------------------------------------------------+ | 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 | +------------------------+---------------------------------------------------------------------------------------------+
I nästa exempel ändrar jag ett av plustecknen till ett minustecken (-
). Det betyder att endast de rader som innehåller ordet Saga
kommer att returneras, men bara om de inte gör det innehåller även Älg
:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('+Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Resultat:
+------------------+-------------------------------------------------------------------------------------------------+ | 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 | +------------------+-------------------------------------------------------------------------------------------------+
Minustecknet används för att utesluta resultat som annars skulle returneras. Därför, om alla våra sökord har ett minustecken prefix, returneras en tom uppsättning.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('-Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Resultat:
Empty set (0.00 sec)
Det finns många fler operatorer som kan användas med booleska sökningar, såsom ~
, <
, > ,
*
, och mer. För mer detaljerad information om hur du använder booleskt läge, se MySQL-dokumentationen för booleska fulltextsökningar.
Exempel 9 – Med Blind Query Expansion
Du kan använda WITH QUERY EXPANSION
eller I NATURAL LANGUAGE-LÄGE MED FRÄGEEXPANSION
modifierare för att utföra blinda frågeexpansion. Detta kan vara användbart när sökfrasen är mycket kort, och där resultaten som returneras kan vara för snäva (därmed utesluter potentiellt relevanta dokument).
Frågeexpansion kan bredda sökningen genom att returnera rader som annars inte skulle returneras. I synnerhet, om en icke-matchande rad innehåller ord som också finns i en matchande rad, kan den icke-matchande raden bli en matchande rad. Med andra ord kan en rad som inte matchar fortfarande returneras, helt enkelt för att den delar andra ord med en matchande rad.
För att demonstrera, här är en normal sökning utan frågeexpansion:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' IN NATURAL LANGUAGE MODE);
Resultat:
+---------+------------+ | AlbumId | AlbumName | +---------+------------+ | 13 | Blue Night | +---------+------------+
Jag angav uttryckligen I NATURAL LANGUAGE LÄGE
men detta är standardläget, så jag kunde också ha utelämnat den här modifieraren om jag hade valt det.
Och här är samma sökning med frågeexpansion:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' WITH QUERY EXPANSION);
Resultat:
+---------+-----------------+ | AlbumId | AlbumName | +---------+-----------------+ | 13 | Blue Night | | 19 | All Night Wrong | +---------+-----------------+
I det här fallet returneras två resultat. Lägg märke till hur det andra resultatet inte innehåller sökfrasen (blå
). Men det innehåller ordet Natt
vilket också råkar vara i det första resultatet. Så den utökade frågan anser att det är tillräckligt bra för att vara en matchning.
Albumnamn är förmodligen inte ett särskilt bra användningsfall för frågeexpansionsläge. Ett bättre användningsfall kan vara en sökning efter säg, databas , där en utökad fråga också kan returnera dokument som innehåller namn som MySQL , Oracle , etc även om de inte innehåller frasen databas .
Här är ett annat exempel. Det här exemplet använder dock dubbla citattecken för att specificera att hela söktermen ska finnas med.
Om vi gör sökningen utan frågeexpansion:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"') LIMIT 3;
Resultat:
+------------------+--------------------------------------------------------------------------------------------------+ | title | description | +------------------+--------------------------------------------------------------------------------------------------+ | ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies | +------------------+--------------------------------------------------------------------------------------------------+
Endast ett resultat returneras (det är det enda resultatet som innehåller hela frasen, exakt som det skrivits).
Men om vi använder blindfrågeexpansion händer det här:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION) LIMIT 3;
Resultat:
+--------------------+------------------------------------------------------------------------------------------------------+ | 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 | +--------------------+------------------------------------------------------------------------------------------------------+
Den första raden är samma som när vi inte använde frågeexpansion. Men frågan går sedan och returnerar rader som bara innehåller delar av vår sökterm. Detta resultat är begränsat till tre bara för att jag använde LIMIT 3
. De faktiska resultaten är mycket bättre:
SELECT COUNT(*) FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION);
Resultat:
+----------+ | COUNT(*) | +----------+ | 1000 | +----------+
Det är mycket möjligt att många av dessa resultat är helt irrelevanta för söktermen. Därför fungerar blind sökning oftast bäst för kortare söktermer.
För mer information om hur du använder blindfrågeexpansion, se MySQL-dokumentationen:Full-Text Searches with Query Expansion.