I MySQL er MATCH()
funktionen udfører en fuldtekstsøgning. Den accepterer en kommasepareret liste over tabelkolonner, der skal søges i.
Tabellen/tabellerne skal have en FULLTEXT
indeks, før du kan lave en fuldtekstsøgning mod dem (selvom booleske forespørgsler mod en MyISAM
søgeindeks kan fungere - om end langsomt - selv uden en FULLTEXT
indeks).
Du kan oprette en FULLTEXT
indeks ved oprettelse af tabellen (ved hjælp af CREATE TABLE
sætning), eller du kan bruge ALTER TABLE
sætning eller CREATE INDEX
sætning, hvis tabellen allerede eksisterer.
Som standard skelner søgningen mellem store og små bogstaver. For at udføre en søgning, der skelner mellem store og små bogstaver, skal du bruge en versalfølsom eller binær sortering for de indekserede kolonner.
Syntaks
Syntaksen for MATCH()
funktionen går sådan her:
MATCH (col1,col2,...) AGAINST (expr [search_modifier])
Hvor col1,col2,...
er den kommaseparerede liste over kolonner, der skal søges i, og expr
er inputstrengen/udtrykket.
Den valgfri search_modifier
argument giver dig mulighed for at angive søgetypen. Det kan være en af følgende værdier:
I NATURLIG SPROG MODUS
I NATURLIG SPROG TILSTAND MED FORESPØRGSELSUDVIDELSE
I BOOLEAN MODE
MED FORESPØRGSELSUDVIDELSE
Standardtilstanden er I NATURAL LANGUAGE MODE
.
Eksempel 1 – Grundlæggende brug
Her er et eksempel på, hvordan du bruger denne funktion:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('cool');
Resultat:
+---------+--------------------+ | AlbumId | AlbumName | +---------+--------------------+ | 5 | Casualties of Cool | +---------+--------------------+
Her er den fulde tabel, som ovenstående forespørgsel blev kørt mod:
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 | +---------+--------------------------+
Eksempel 2 – Fejl:"Kan ikke finde FULLTEXT-indekset"
InnoDB
tabeller skal have en FULLTEXT
indeks, før det vil returnere resultater fra en fuldtekstsøgning. Hvis den ikke har en FULLTEXT
indeks, vil du sandsynligvis få følgende fejl:
ERROR 1191 (HY000): Can't find FULLTEXT index matching the column list
Hvis du får denne fejl, skal du tilføje en FULLTEXT
indeks for alle kolonner, som du forsøger at søge i (se næste eksempel).
Undtagelsen fra dette kan være, hvis du kører en boolsk forespørgsel mod en MyISAM
søgeindeks.
For at være mere specifik angiver MySQL-dokumentationen for boolske fuldtekstsøgninger følgende:
InnoDB
tabeller kræver en FULLTEXT
indeks på alle kolonner i MATCH()
udtryk for at udføre booleske forespørgsler. Booleske forespørgsler mod en MyISAM
søgeindeks kan fungere selv uden en FULLTEXT
indeks, selvom en søgning udført på denne måde ville være ret langsom.
Eksempel 3 – Tilføjelse af et FULLTEXT-indeks til en eksisterende tabel
Her er et eksempel på tilføjelse af en FULLTEXT
indeks til en eksisterende tabel:
ALTER TABLE Albums ADD FULLTEXT(AlbumName);
I dette tilfælde indekserede jeg indholdet af AlbumName
kolonne.
For at indeksere flere kolonner skal du adskille dem med et komma (se næste eksempel).
Eksempel 4 – Søgning i flere kolonner
Hvis du tror, du skal søge i mere end én kolonne, skal du oprette et indeks, der inkluderer alle kolonner, der skal søges i. For at gøre dette skal du blot inkludere hver kolonne som en kommasepareret liste.
Her er et eksempel, hvor jeg tilføjer en FULLTEXT
indeks til filmen
tabel (som er en del af Sakila-eksempeldatabasen).
ALTER TABLE film ADD FULLTEXT(title, description);
I dette tilfælde indekserer jeg indholdet af titlen
og beskrivelse
kolonner.
Nu hvor vi har oprettet en FULLTEXT
indeks for begge kolonner, kan vi lave en fuldtekstsøgning mod 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 | +-------------------+-----------------------------------------------------------------------------------------------------------+
Her er en anden søgning, hvor den nøjagtige nøglesætning ikke matcher, men hvert søgeord i den sætning gør:
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 | +-------------+---------------------------------------------------------------------------------------------------------+
Hvis du kun vil have den nøjagtige sætning til at matche, skal du sætte dobbelte anførselstegn rundt om den:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Iron Maiden"');
Resultat:
Empty set (0.00 sec)
I dette tilfælde indeholder ingen af kolonnerne den nøjagtige sætning.
Eksempel 5 – Returner relevansresultatet
Hver gang du bruger MATCH()
funktion, tildeles hver række i tabellen en relevansværdi. Med andre ord får hver række en score, der afgør, hvor relevant den er for søgetermen. Resultaterne sorteres derefter efter relevans (højeste relevans først).
Relevansværdier er ikke-negative flydende decimaltal. Nul relevans betyder ingen lighed. Relevans beregnes ud fra antallet af ord i rækken (dokumentet), antallet af unikke ord i rækken, det samlede antal ord i samlingen og antallet af rækker, der indeholder et bestemt ord.
For at returnere relevansen af hvert resultat skal du blot inkludere MATCH()
funktion i din liste over kolonner for at vælge.
Eksempel:
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 dette tilfælde er relevansscoren meget høj for begge rækker.
Her er endnu en, hvor relevansen er lavere:
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 | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Bemærk, at resultatsættet ville have været meget større, hvis jeg ikke havde brugt LIMIT 15
for at begrænse antallet af resultater til 15.
Eksempel 6 – Giv kun resultater over en bestemt relevansscore
Vi kan tage det foregående eksempel et skridt videre og kun filtrere de resultater fra med en vis relevansscore. I dette tilfælde specificerer jeg, at relevansscoren skal være højere end 2.
Vær dog forsigtig, når du gør dette. Som det ses ovenfor, kan relevansværdier være meget høje eller meget lave, afhængigt af faktorer såsom hvor meget tekst der er i kolonnen, hvor mange andre rækker der matcher søgetermen osv.
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 | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Eksempel 7 – Inkluder resultater med nulrelevans
Her er et eksempel på en liste over relevansværdierne for hver række, selvom relevansværdien er nul. Vi kan gøre dette ved ikke at bruge MATCH()
funktion i WHERE
klausul.
I dette eksempel bruger jeg faktisk ikke en WHERE
klausul. Jeg bruger kun en LIMIT
klausul for at begrænse antallet af resultater.
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 | +-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+
Eksempel 8 – Boolean tilstand
MySQL giver os mulighed for at køre fuldtekstsøgninger i boolsk tilstand. For at gøre dette skal du tilføje I BOOLEAN MODE
modifikator til din forespørgsel.
Boolesk tilstand giver dig mulighed for at bruge operatorer såsom +
og -
for at angive, om et bestemt ord eller en bestemt sætning skal eller ikke skal være til stede.
I det følgende eksempel præfikser jeg hvert ord med et plustegn (+
) for at angive, at begge ord skal være til stede.
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 det næste eksempel ændrer jeg et af plustegnet til et minustegn (-
). Det betyder, at kun de rækker, der indeholder ordet Saga
vil blive returneret, men kun hvis de ikke gør det indeholder også Elg
:
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 | +------------------+-------------------------------------------------------------------------------------------------+
Minustegnet bruges til at udelukke resultater, der ellers ville blive returneret. Derfor, hvis alle vores søgeord er foranstillet med et minustegn, returneres et tomt sæt.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('-Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Resultat:
Empty set (0.00 sec)
Der er mange flere operatorer, der kan bruges med booleske søgninger, såsom ~
, <
, > ,
*
, og mere. For mere detaljerede oplysninger om brug af boolesk tilstand, se MySQL-dokumentationen for boolske fuldtekstsøgninger.
Eksempel 9 – Med Blind Query Expansion
Du kan bruge WITH QUERY EXPANSION
eller I NATURAL LANGUAGE MODE MED FORESPØRGSUDVIDELSE
modifikatorer til at udføre blindforespørgselsudvidelse. Dette kan være nyttigt, når søgesætningen er meget kort, og hvor de returnerede resultater kan være for snævre (dermed udelukker potentielt relevante dokumenter).
Forespørgselsudvidelse kan udvide søgningen ved at returnere rækker, som ellers ikke ville blive returneret. Især hvis en ikke-matchende række indeholder ord, der også er indeholdt i en matchende række, kan den ikke-matchende række blive en matchende række. Med andre ord kan en ikke-matchende række stadig returneres, simpelthen fordi den deler andre ord med en matchende række.
For at demonstrere er her en normal søgning uden forespørgselsudvidelse:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' IN NATURAL LANGUAGE MODE);
Resultat:
+---------+------------+ | AlbumId | AlbumName | +---------+------------+ | 13 | Blue Night | +---------+------------+
Jeg har udtrykkeligt anført I NATURAL LANGUAGE MODE
men dette er standardtilstanden, så jeg kunne også have udeladt denne modifikator, hvis jeg havde valgt det.
Og her er den samme søgning med forespørgselsudvidelse:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' WITH QUERY EXPANSION);
Resultat:
+---------+-----------------+ | AlbumId | AlbumName | +---------+-----------------+ | 13 | Blue Night | | 19 | All Night Wrong | +---------+-----------------+
I dette tilfælde returneres to resultater. Bemærk, hvordan det andet resultat ikke indeholder søgesætningen (blå
). Men det indeholder ordet Nat
hvilket tilfældigvis også er i det første resultat. Så den udvidede forespørgsel vurderer, at det er godt nok til at være et match.
Albumnavne er sandsynligvis ikke et særligt godt eksempel på forespørgselsudvidelsestilstand. En bedre use case kan være en søgning efter f.eks. database , hvor en udvidet forespørgsel også kan returnere dokumenter, der indeholder navne som MySQL , Oracle osv., selvom de ikke indeholder sætningen database .
Her er et andet eksempel. Dette eksempel bruger dog dobbelte anførselstegn for at angive, at hele søgetermen skal være til stede.
Hvis vi foretager søgningen uden forespørgselsudvidelse:
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 | +------------------+--------------------------------------------------------------------------------------------------+
Kun ét resultat returneres (det er det eneste resultat, der indeholder hele sætningen, nøjagtigt som skrevet).
Men hvis vi bruger blindforespørgselsudvidelse, sker der her:
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ørste række er den samme, som da vi ikke brugte forespørgselsudvidelse. Men forespørgslen går så hen og returnerer rækker, der kun indeholder dele af vores søgeord. Dette resultat er begrænset til tre, fordi jeg brugte LIMIT 3
. De faktiske resultater er meget større:
SELECT COUNT(*) FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION);
Resultat:
+----------+ | COUNT(*) | +----------+ | 1000 | +----------+
Det er meget muligt, at mange af disse resultater er fuldstændig irrelevante for søgetermen. Derfor fungerer blind forespørgselsudvidelse normalt bedst for kortere søgetermer.
Se MySQL-dokumentationen:Full-Text Searches with Query Expansion for at få flere oplysninger om brug af blind forespørgselsudvidelse.