In MySQL, il MATCH()
la funzione esegue una ricerca full-text. Accetta un elenco separato da virgole di colonne di tabella da cercare.
Le tabelle devono avere un FULLTEXT
index prima di poter eseguire una ricerca full-text su di essi (sebbene query booleane su un MyISAM
l'indice di ricerca può funzionare, anche se lentamente, anche senza un FULLTEXT
indice).
Puoi creare un FULLTEXT
index durante la creazione della tabella (usando il CREATE TABLE
istruzione), oppure puoi utilizzare ALTER TABLE
o il CREATE INDEX
istruzione se la tabella esiste già.
Per impostazione predefinita, la ricerca non fa distinzione tra maiuscole e minuscole. Per eseguire una ricerca con distinzione tra maiuscole e minuscole, utilizzare regole di confronto binarie o con distinzione tra maiuscole e minuscole per le colonne indicizzate.
Sintassi
La sintassi per MATCH()
la funzione va così:
MATCH (col1,col2,...) AGAINST (expr [search_modifier])
Dove col1,col2,...
è l'elenco di colonne separate da virgole da cercare e expr
è la stringa/espressione di input.
Il search_modifier
facoltativo argomento consente di specificare il tipo di ricerca. Può essere uno qualsiasi dei seguenti valori:
IN NATURAL LANGUAGE MODE
IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
IN BOOLEAN MODE
WITH QUERY EXPANSION
La modalità predefinita è IN NATURAL LANGUAGE MODE
.
Esempio 1 – Utilizzo di base
Ecco un esempio di come utilizzare questa funzione:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('cool');
Risultato:
+---------+--------------------+ | AlbumId | AlbumName | +---------+--------------------+ | 5 | Casualties of Cool | +---------+--------------------+
Ecco la tabella completa su cui è stata eseguita la query precedente:
SELECT AlbumId, AlbumName FROM Albums;
Risultato:
+---------+--------------------------+ | 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 | +---------+--------------------------+
Esempio 2 – Errore:"Impossibile trovare l'indice FULLTEXT"
InnoDB
le tabelle devono avere un FULLTEXT
index prima che restituisca i risultati di una ricerca full-text. Se non ha un FULLTEXT
index, probabilmente riceverai il seguente errore:
ERROR 1191 (HY000): Can't find FULLTEXT index matching the column list
Se ricevi quell'errore, dovrai aggiungere un FULLTEXT
indice per tutte le colonne che stai cercando di cercare (vedi il prossimo esempio).
L'eccezione potrebbe essere se stai eseguendo una query booleana su un MyISAM
indice di ricerca.
Per essere più specifici, la documentazione MySQL per le ricerche full-text booleane afferma quanto segue:
InnoDB
le tabelle richiedono un FULLTEXT
indice su tutte le colonne di MATCH()
espressione per eseguire query booleane. Query booleane su un MyISAM
l'indice di ricerca può funzionare anche senza un FULLTEXT
index, anche se una ricerca eseguita in questo modo sarebbe piuttosto lenta.
Esempio 3:aggiunta di un indice FULLTEXT a una tabella esistente
Ecco un esempio di aggiunta di un FULLTEXT
indice in una tabella esistente:
ALTER TABLE Albums ADD FULLTEXT(AlbumName);
In questo caso, ho indicizzato il contenuto di AlbumName
colonna.
Per indicizzare più colonne, separale con una virgola (vedi il prossimo esempio).
Esempio 4:ricerca in più colonne
Se ritieni di dover cercare in più di una colonna, dovrai creare un indice che includa tutte le colonne da cercare. Per fare ciò, includi semplicemente ogni colonna come un elenco separato da virgole.
Ecco un esempio in cui aggiungo un FULLTEXT
indice del film
tabella (che fa parte del database di esempio Sakila).
ALTER TABLE film ADD FULLTEXT(title, description);
In questo caso, indico il contenuto del title
e description
colonne.
Ora che abbiamo creato un FULLTEXT
index per entrambe le colonne, possiamo eseguire una ricerca full-text su di esse:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('vertigo');
Risultato:
+-------------------+-----------------------------------------------------------------------------------------------------------+ | title | description | +-------------------+-----------------------------------------------------------------------------------------------------------+ | VERTIGO NORTHWEST | A Unbelieveable Display of a Mad Scientist And a Mad Scientist who must Outgun a Mad Cow in Ancient Japan | +-------------------+-----------------------------------------------------------------------------------------------------------+
Ecco un'altra ricerca, in cui la frase chiave esatta non corrisponde, ma ogni parola chiave all'interno di quella frase lo fa:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('Iron Maiden');
Risultato:
+-------------+---------------------------------------------------------------------------------------------------------+ | 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 | +-------------+---------------------------------------------------------------------------------------------------------+
Se vuoi che solo la frase esatta corrisponda, metti le virgolette intorno ad essa:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Iron Maiden"');
Risultato:
Empty set (0.00 sec)
In questo caso, nessuna delle colonne contiene quella frase esatta.
Esempio 5 – Restituire il punteggio di pertinenza
Ogni volta che usi MATCH()
funzione, a ogni riga della tabella viene assegnato un valore di rilevanza. In altre parole, ogni riga ottiene un punteggio che determina quanto sia rilevante per il termine di ricerca. I risultati vengono quindi ordinati per pertinenza (prima la pertinenza più alta).
I valori di rilevanza sono numeri a virgola mobile non negativi. Pertinenza zero significa nessuna somiglianza. La pertinenza viene calcolata in base al numero di parole nella riga (documento), al numero di parole univoche nella riga, al numero totale di parole nella raccolta e al numero di righe che contengono una parola particolare.
Per restituire la pertinenza di ogni risultato, includi semplicemente il MATCH()
funzione nell'elenco di colonne da selezionare.
Esempio:
SELECT MATCH(title, description) AGAINST('Iron Maiden') AS Relevance, title, description FROM film WHERE MATCH(title, description) AGAINST('Iron Maiden');
Risultato:
+-----------+-------------+---------------------------------------------------------------------------------------------------------+ | 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 | +-----------+-------------+---------------------------------------------------------------------------------------------------------+
In questo caso il punteggio di pertinenza è molto alto per entrambe le righe.
Eccone un altro in cui la rilevanza è inferiore:
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;
Risultato:
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | 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 | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Nota che il set di risultati sarebbe stato molto più grande se non avessi usato LIMIT 15
per limitare il numero di risultati a 15.
Esempio 6 – Restituire solo risultati al di sopra di un determinato punteggio di pertinenza
Possiamo fare un ulteriore passo avanti nell'esempio precedente e filtrare solo i risultati con un determinato punteggio di pertinenza. In questo caso specifico che il punteggio di rilevanza deve essere maggiore di 2.
Fai attenzione quando lo fai però. Come visto sopra, i valori di pertinenza possono essere molto alti o molto bassi, a seconda di fattori quali la quantità di testo nella colonna, quante altre righe corrispondono al termine di ricerca, ecc.
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;
Risultato:
+--------------------+------------------------+---------------------------------------------------------------------------------------------------------+ | 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 | +--------------------+------------------------+---------------------------------------------------------------------------------------------------------+
Esempio 7 – Includi risultati di rilevanza zero
Ecco un esempio di elenco dei valori di pertinenza per ogni riga, anche se il valore di pertinenza è zero. Possiamo farlo non usando il MATCH()
funzione nel WHERE
clausola.
In questo esempio, in realtà non utilizzo un WHERE
clausola. Uso solo un LIMIT
clausola per limitare il numero di risultati.
SELECT MATCH(title, description) AGAINST('Scientist') AS Relevance, title, description FROM film LIMIT 15;
Risultato:
+-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+ | 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 | +-------------------+------------------+-----------------------------------------------------------------------------------------------------------------------+
Esempio 8 – Modalità booleana
MySQL ci consente di eseguire ricerche full-text in modalità booleana. Per fare ciò, aggiungi il IN BOOLEAN MODE
modificatore della tua query.
La modalità booleana ti consente di utilizzare operatori come +
e -
per specificare se una particolare parola o frase deve o non deve essere presente.
Nell'esempio seguente, prefisso ogni parola con un segno più (+
) per indicare che entrambe le parole devono essere presenti.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('+Saga +Moose' IN BOOLEAN MODE) LIMIT 3;
Risultato:
+------------------------+---------------------------------------------------------------------------------------------+ | 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 | +------------------------+---------------------------------------------------------------------------------------------+
Nel prossimo esempio, cambio uno dei segni più in un segno meno (-
). Ciò significa che solo quelle righe che contengono la parola Saga
verranno restituiti, ma solo se non contengono anche Moose
:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('+Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Risultato:
+------------------+-------------------------------------------------------------------------------------------------+ | 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 | +------------------+-------------------------------------------------------------------------------------------------+
Il segno meno viene utilizzato per escludere risultati che altrimenti verrebbero restituiti. Pertanto, se tutte le nostre parole di ricerca sono precedute da un segno meno, viene restituito un insieme vuoto.
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('-Saga -Moose' IN BOOLEAN MODE) LIMIT 3;
Risultato:
Empty set (0.00 sec)
Ci sono molti altri operatori che possono essere utilizzati con le ricerche booleane, come ~
, <
, >
, *
, e altro ancora. Per informazioni più dettagliate sull'utilizzo della modalità booleana, vedere la documentazione MySQL per le ricerche booleane full-text.
Esempio 9 – Con espansione query cieca
Puoi usare WITH QUERY EXPANSION
o il IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION
modificatori per eseguire l'espansione della query cieca. Questo può essere utile quando la frase di ricerca è molto breve e quando i risultati restituiti potrebbero essere troppo stretti (escludendo quindi documenti potenzialmente rilevanti).
L'espansione della query può ampliare la ricerca restituendo righe che altrimenti non verrebbero restituite. In particolare, se una riga non corrispondente contiene parole che sono anche contenute in una riga corrispondente, tale riga potrebbe diventare una riga corrispondente. In altre parole, è ancora possibile restituire una riga non corrispondente, semplicemente perché condivide altre parole con una riga corrispondente.
Per dimostrare, ecco una normale ricerca senza espansione della query:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' IN NATURAL LANGUAGE MODE);
Risultato:
+---------+------------+ | AlbumId | AlbumName | +---------+------------+ | 13 | Blue Night | +---------+------------+
Ho dichiarato esplicitamente IN NATURAL LANGUAGE MODE
ma questa è la modalità predefinita, quindi avrei anche potuto omettere questo modificatore se lo avessi scelto.
Ed ecco la stessa ricerca con espansione della query:
SELECT AlbumId, AlbumName FROM Albums WHERE MATCH(AlbumName) AGAINST('Blue' WITH QUERY EXPANSION);
Risultato:
+---------+-----------------+ | AlbumId | AlbumName | +---------+-----------------+ | 13 | Blue Night | | 19 | All Night Wrong | +---------+-----------------+
In questo caso, vengono restituiti due risultati. Nota come il secondo risultato non contiene la frase di ricerca (blue
). Ma contiene la parola Night
che è anche nel primo risultato. Quindi la query espansa lo ritiene sufficientemente buono per essere una corrispondenza.
I nomi degli album probabilmente non sono un ottimo caso d'uso per la modalità di espansione delle query. Un caso d'uso migliore potrebbe essere la ricerca, ad esempio, di database , dove una query espansa potrebbe anche restituire documenti che contengono nomi come MySQL , Oracolo , ecc anche se non contengono la frase database .
Ecco un altro esempio. Tuttavia, questo esempio utilizza le virgolette doppie per specificare che l'intero termine di ricerca deve essere presente.
Se facciamo la ricerca senza espansione della query:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"') LIMIT 3;
Risultato:
+------------------+--------------------------------------------------------------------------------------------------+ | title | description | +------------------+--------------------------------------------------------------------------------------------------+ | ACADEMY DINOSAUR | A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies | +------------------+--------------------------------------------------------------------------------------------------+
Viene restituito un solo risultato (è l'unico risultato che contiene l'intera frase, esattamente come digitata).
Ma se utilizziamo l'espansione delle query cieche, ecco cosa succede:
SELECT title, description FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION) LIMIT 3;
Risultato:
+--------------------+------------------------------------------------------------------------------------------------------+ | 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 prima riga è la stessa di quando non abbiamo utilizzato l'espansione della query. Tuttavia, la query quindi va e restituisce righe che contengono solo parti del nostro termine di ricerca. Questo risultato è limitato a tre solo perché ho usato LIMIT 3
. I risultati effettivi sono molto maggiori:
SELECT COUNT(*) FROM film WHERE MATCH(title, description) AGAINST('"Feminist And a Mad Scientist"' WITH QUERY EXPANSION);
Risultato:
+----------+ | COUNT(*) | +----------+ | 1000 | +----------+
È del tutto possibile che molti di questi risultati siano completamente irrilevanti per il termine di ricerca. Pertanto, l'espansione delle query cieche di solito funziona meglio per termini di ricerca più brevi.
Per ulteriori informazioni sull'utilizzo dell'espansione delle query cieche, consulta la documentazione di MySQL:ricerche full-text con espansione delle query.