Ricerca full-text in un database MySQL

La differenza
Noi ci concentreremo appunto sull'ultimo metodo diricerca. Le differenze tra i vari metodi sono numerose, maper quale motivo usare una ricerca full-text?
La ricerca full-text possiede numerosi vantaggi: per primacosa è migliore a livello di prestazioni (consentericerche più veloci), e poi consente ricerche moltoprecise ordinando anche i risultati in base al grado diattinenza con la ricerca, in parole povere pesa i risultati.Per comprendere meglio l'utilità della ricercafull-text proviamo a pensare a Google. Quando si effettua unaricerca con Google i risultati vengono mostrati in base algrado di attinenza con la parola cercata. Questo èproprio quello che la ricerca full-text permette di fare.

La ricerca full-text si basa su indici, il che significa chela ricerca viene svolta duplicemente: innanzitutto MySQLricerca il termine nell'indice e poi esegue la ricercavera e propria. Per chiarire questo concetto provate apensare di dover cercare in uno stradario di una qualchecittà "via Milano 54". Una ricerca condottain modo classico inizierebbe a sfogliare tutte le carte dellostradario analizzandole fino a trovare la via desiderata. Unaricerca full-text invece per prima cosa va a consultarel'indice. Qui trova la via desiderata corredata dalleinformazioni per localizzarla sulle carte. Con taliinformazioni estrae poi la carta esatta. Si capisce bene chein questo modo la ricerca è molto più veloce edefficiente. E' stato verificato che su un database di100MB una ricerca di tipo full-text si dimostra circa 8/10volte più veloce di una ricerca libero (con"LIKE").

Precisazioni iniziali
Bisogna precisare fin dall'inizio che la ricercafull-text è possibile solo su campi di testo, quindiCHAR, VARCHAR, TEXT ecc... Inoltre è possibile solo acondizione che sia stato creato un full-text index.L'indice full-text può essere creato al momentodella creazione della tabella o anche su una tabellaesistente. Per aggiungere l'indice ad una tabellaesistente si può fare:

ALTER TABLE nomeTabella ADD FULLTEXT(primoCampo,secondoCampo, terzoCampo, ...);

Se invece si deve creare una nuova tabella l'indice sipuò creare ugualmente aggiungendo FULLTEXT:

CREATE TABLE nomeTabella (
      primoCampo INTUNSIGNED   AUTO_INCREMENT NOT NULL PRIMARYKEY,
      secondoCampo VARCHAR(200),
        terzoCampo TEXT,
      FULLTEXT (secondoCampo, terzoCampo)
  );

 

Ovviamente dentro FULLTEXT() bisogna inserire tutti i campisu cui creare l'indice full-text separati da una virgola" ,".
E' doveroso ricordare inoltre che la ricerca full-textè possibile solo dalla versione 3.23.23 e successivedi MySQL.

Query di ricerca
Vediamo come usare la ricerca full-text. Se ad esempiovogliamo cercare la parola "milano" nei campi"indirizzo" , "nome" ,"descrizione" della tabella "locali" delnostro database, potremmo usare la seguente query:

SELECT * FROM locali WHERE MATCH(indirizzo, nome,descrizione) AGAINST('milano')

 

La sequenza di comandi MATCH() ... AGAINST() restituisce ilvalore di attinenza del risultato con il testo cercato(numero in floating-point compreso tra 0 e 10). Quindi,considerando che la clausola WHERE per essere verificata deveavere valore booleano "true" , se il risultato inquestione ha attinenza 0 su 10, ovvero non ha nessunaattinenza, viene scartato. Vengono quindi selezionati soloquei risultati con attinenza maggiore di 0. Questa querytuttavia non ha grande utilità, in quanto non ordina irisultati secondo la loro attinenza, nè tantomenorestituisce il valore di essa. Potremmo modificare la queryin modo che ordini i risultati per attinenza e restituisca ilvalore della stessa riga per riga:

SELECT *, MATCH(indirizzo, nome, descrizione)AGAINST('milano') AS attinenza FROM locali WHEREMATCH(indirizzo, nome, descrizione) AGAINST('milano')ORDER BY attinenza DESC

 

In questo modo vengono restituiti tutti i campi e inpiù anche il valore dell'attinenza del risultatorispetto alla parola "milano" , e le righe vengonoordinate da quella con più attinenza a quella che neha meno.

Possiamo anche fare la ricerca di tutti quei risultati chehanno parole che iniziano o terminano per "milano".Ciò si ottiene con il carattere jolly "*" ,che indica qualsiasi lettera. Quindi:

AGAINST("milano*") // cerca tutti i recordcon parole che iniziano per "milano"
AGAINST("*milano") // cerca tutti i record conparole che terminano per "milano"

 

Ricerca di concetti: il boolean mode
A partire dalla versione 4.0.1 di MySQL e successiveè possibile combinare alla ricerca full-text ilboolean mode: in parole povere è possibile effettuarericerche con operatori booleani come si può fare con imotori di ricerca.
Facciamo un esempio pratico: se volessimo fare una ricercacome la precedente, cercando per tutti i risultati in cuicompaia la parola "milano" ma contemporaneamentenon compaia la parola "roma" , potremmo usare unaquery di questo tipo:

SELECT *, MATCH(indirizzo, nome, descrizione)AGAINST('+milano -roma' IN BOOLEAN MODE) AS attinenzaFROM locali WHERE MATCH(indirizzo, nome, descrizione)AGAINST('+milano -roma' IN BOOLEAN MODE) ORDER BYattinenza DESC

 

Come si può notare è stata aggiunta la clausola"IN BOOLEAN MODE" all'interno di AGAINST e sonostati aggiunti anche gli operatori booleani + e -all'interno del testo da cercare. Vediamo quali sonoalcuni dei casi possibili per il testo di ricerca:

  • 'milano roma': deve essere presente uno dei due termini
  • '+milano +roma': devono essere presenti entrambi i termini
  • '+milano roma': deve essere presente "milano" ed eventualmente "roma".
  • '+milano -roma': deve essere presente "milano" ma non "roma"
  • '+milano +(<roma >venezia)': devono essere presenti o "milano" e "roma" o "milano" e "venezia" , ma i records con "milano" e "venezia" hanno rilevanza maggiore. ("<" indica minore rilevanza, ">" indica maggiore rilevanza)
  • '"milano roma"': deve essere presente l'esatta sequenza "milano roma".