Full Text Search je opcija koja omogućava brzu pretragu kroz velike količine teksta. Ovo je dobar, funkcionalan, jednostavan i brz sistem i što je najvažnije, nezamenljiv u nekim situacijama.
Osnova Engine FTS-a je sledeća:
Prilikom indeksiranja, indekser parsira tekst i preuzima iz njega reči. Svaka reč smešta se u indeks pod određenim brojem. Takođe, polje sa koga je tekst preuzet, pamti se pod određenim brojem. Na kraju, indekser pravi relaciju između polja sa tekstom i rečima koje tom polju pripadaju.
Kada dođe do pretrage, Engine prvo pronađe tražene reči, zatim izlista njihove relacije (u relacijama se pamti i broj pojavljivanja reči u polju), a zatim na osnovu tih relacija sortiranih po broju pojavljivanja reči, dobijamo i sama polja (odnosno, brojeve tih polja).
Ovakav način indeksiranja naziva se invertovano indeksiranje.
Da bismo efikasnije testirali, biće nam potrebna neka malo veća baza. Na primer, možemo preuzeti bazu Classic Models (baza za testiranje - prodavnica oldtajmera).
Najjednostavniji način da ovu bazu postavite na MySQL server je putem MySQL Query pretraživača.
Nakon što preuzmete fajl sa bazom, otvorite ga u nekom tekst editoru (najbolje običan Notepad) i kopirajte njegov sadržaj u MySQL Query Browser Script Editor (File > New Script Tab). Pritisnite Execute i baza će biti postavljena na server.
Alternativno, možete bazu instalirati i uz pomoć MySQL monitora, sledećim setom naredbi:
create database classicmodels;
use classicmodels;
source classicmodels.sql;
Vratimo se u MySQL Query Browser. Možete nakon ovoga obrisati Script Tab i vratiti se u Resultset Tab. Ako već niste, pozicionirajte se na bazu Classicmodels (dvoklikom ili naredbom Use Classicmodels).
Odmah ćemo zadati upit koji zahteva da tekst u productdescription koloni sadrži određenu reč. To je nešto što svakako očekujemo da možemo dobiti od jedne baze podataka.
Pokušajmo da pronađemo reč Replica (ova reč se pominje u nekim opisima).
Da bismo našli ovu reč, potrebno je da kažemo serveru da će tražena reč biti deo teksta. Kada bi upit izgledao ovako, ne bismo dobili ni jedan red u rezultatu:
select * from products where productdescription like 'replica'
Dakle, moramo se pomoći džoker znacima. Ovaj upit, vratiće dobar rezultat. Sve tekstove u kojima postoji reč Replica:
select * from products where productdescription like '% replica %'
Ali po kojoj ceni? U celoj tabeli ima 110 redova i ukoliko pogledamo vreme za koje je izvršen upit, videćemo da je veoma slično vremenu za koje bi bio izvršen upit sa Full Text indeksom. Ali, kada bi bilo više hiljada redova, rezultat bi se drastično razlikovao.
Napravimo sada Full atext indeks na koloni productdescription:
Prvo editujemo tabelu products:
Zatim, pravimo Full Tekst indeks, na koloni productdescription, na ništa drugačiji način od onoga kako smo pravili i ostale indekse u prethodnoj lekciji. Sa tom razlikom što ćemo ovde za Index Kind podesiti vrednost FULLTEXT.
Kada ovo uradimo, potvrđujemo tasterom Apply Changes. Upit koji će aplikacija tražiti da izvrši, mogli smo, naravno, uneti i ručno (umesto grafičkog kreiranja indeksa):
ALTER TABLE `classicmodels`.`products` ADD FULLTEXT INDEX `fti_productdescription`(`productDescription`);
Za kreiranje full text index-a uz pomoć MySql Workbench-a koristi se ista procedura kao i za kreiranje bilo kog drugog indeksa, samo što se iz liste tipova, odabira FULLTEXT Index:
Takođe, Full Text indeks može se kreirati i prilikom same kreacije tabele:
create table testTable
(
id int primary key auto_increment not null,
mojtekst text,
fulltext(mojtekst)
) engine MyIsam;
Upit sličan malopređašnjem dobićete izmenom uslovnog izraza (where):
select * from products where match(productdescription) against('replica')
Možete napraviti eksperiment sa brzinom; tako što ćete napraviti novu tabelu i ispuniti je podacima iz tabele products:
create table prTmp (prDesc text, fulltext(prDesc)) engine MyIsam
insert into prTmp select productdescription from products
Drugi (Insert) upit ponovite što više puta, kako bi se tabela napunila podacima, a zatim pokušajte da naizmenično vršite pretragu putem standardnih i Full Text Search upita.
Pogledajmo kako bi standardno izgledao upit koji bi trebalo da proveri da li postoji deo teksta Deluxe Coupe:
select productdescription from products where productdescription like '%deluxe%' or productdescription like '%coupe%';
Dobićemo dva reda u rezultatu.
Ista ta dva reda dobićemo ako upotrebimo Full Text upit:
select productdescription from products where match(productdescription) against('coupe deluxe')
Ali u ova dva slučaja, redovi neće biti sortirani na isti način.
To je zato što obični upiti, kada pronađu određeni uslov u polju, emutuju ga kao rezultat, pri čemu se sam rezultat sortira standardno.
Sa druge strane, Full Text indeks uzima u obzir relevantnost pronađenog rezultata i u stanju je da sortira na osnovu njega.
U primeru, jedan tekst sadrži samo reč Coupe, dok drugi sadrži obe reči i to baš u traženom obrascu. Za običan SQL upit, oba teksta ispunjavaju uslov (postoji jedna od dve tražene reči), ali Full Text Search, pored toga, uzima u obzir i to u kolikoj meri je koji uslov ispunjen i zato sortira rezultate pravilno.
Na sličan način bismo mogli uzeti u obzir i još kolona prilikom pretrage:
select productdescription from products where match(productdescription,productname) against('coupe deluxe')
Pokušajte sami da kreirate istu verziju običnog upita.
Prilikom pretrage, moguće je izvršiti i filtraciju ciljnog sadržaja. Ali se, u tom slučaju, mora dodati naredba in boolean mode nakon uslovnog teksta:
select productdescription from products
where match(productdescription) against('+coupe +deluxe' in boolean mode);
Ovaj upit vratiće samo redove koji sadrže reči Coupe i Deluxe zato što reč iza operatora + mora biti prisutna kako bi rezultat bio uzet u obzir. Ako bi uslov bio samo ‘coupe +deluxe’ ili ‘+coupe deluxe’, bili bi uzeti u obzir svi rezultati koji imaju operator + ispred ciljne reči, ali bi bolje pozicionirani bili oni koji uz to imaju i reč bez operatora.
Na sličan način možemo postaviti i uslov da neka reč ne bude u rezultatu. Na primer: '+coupe -deluxe' će vratiti sve rezultate u kojima postoji reč Coupe, ali ne postoji reč Deluxe.
Oznakama < i > možemo uticati na relevantnost određenih reči. Sledeći uslov, rezultiraće svim poljima koja sadrže reči Coupe Deluxe ili Coupe Standard, ali će biti bolje pozicionirani oni redovi, čije ciljno polje ima reči Coupe Deluxe.
'+coupe >deluxe <standard'
Oznaka * predstavlja džoker. 'a*' vraća sve reči koje počinju slovom a.
Male zagrade omogućavaju ubacivanje podizraza:
'+coupe (>deluxe <standard +(<car >limousine))'
Iz teksta se vidi da je Full Text indeks veoma brza i moćna alatka. Ipak, treba obratiti pažnju na to da katalozi Full Text indeksa zauzimaju dodatni prostor.
Takođe, Full Text indeks funkcioniše samo na MyIsam mehanizmu skladištenja i na kolonama tekstualnog tipa: varchar, char, text...
Bazu classicmodels nemojte brisati sa MySQL servera.
Najvažnije iz lekcije: