MySQL fulltext keresés

MySQL fulltext keresés

A programozó lét fő mozgatóereje a lustaság maga, ami arra ösztönzi a kódbogarászó népséget, hogy egy bonyolult megoldás helyett keressen inkább valami egyszerűbbet és gyorsabban kivitelezhetőbbet, még ha maga a keresés tovább tart is, mint a bonyolult megoldás megvalósítása. Mindenkinek megvannak a maga rémálmai és kevésbé kedvelt részei. Egy különböző operátorokkal működő keresőkifejezést feldolgozó és súlyozott eredményeket visszaadó kód, ami még ezen felül MySQL-ből szedi a bejegyzéseket... Hát bőven lehet egy rémálom főszereplője (persze az már teljesen más kérdés, ha az ember kihívásként tekint rá, és alig várja, hogy megfelelő megoldást találjon).

Mint az érezhető volt a bevezetőből (és a címből :D), maradunk a MySQL vonalon, gyorsan át is vesszük, hogy milyen lehetőségeink vannak, ha egy szöveg típusú oszlopban szeretnénk adott dolgokat keresni:

SELECT * FROM `table` WHERE `col` LIKE '%text%';
A legegyszerűbb és talán a leggyorsabb változat. Megfelelő ha csak egy szóra, szórészletre akarunk keresni, vagy ha PHP oldalon megírjuk a keresőkifejezés értelmezőt, amit aztán átfordítunk ilyen LIKE feltételek sorozatává.
SELECT * FROM `table` WHERE `col` RLIKE '^text$';
Egy fokkal megbonyolított dolog, ez esetben már használhatunk reguláris kifejezéseket a keresendő szóösszetétel megtalálására, ami elég szép és pontos eredményhez vezethet. Persze ha elég türelmesek vagyunk ahhoz, hogy kivárjuk.

Ezzel el is érkeztünk a fő témánkhoz, ami nem más, mint a MySQL egy indexelési típusa, a FULLTEXT. Nézzünk rögtön egy példát a használat szintaxisra:

SELECT * FROM `table` WHERE MATCH (`col`) AGAINST ('szó1, szó2 szó3');

Ebben az esetben a MySQL megpróbálja az AGAINST utáni kifejezést szavakra bontani, szokásos elválasztókat keresve (pont, vessző, szóköz). Az olyan szavakat, amik a sorok több mint 50%-ában jelen vannak, nem vesznek részt a keresésben. Emellett vannak ugynevezett "stopword"-ök is, amik alapból kihagyásra kerülnek (például a "the", "and", "but"). A kapott sorok a hozzárendelt súlyozás szerint lesznek csökkenő sorrendben rendezve. Ha magára a súlyozásra vagyunk kiváncsiak, lekérhetjük azt is:

SELECT MATCH (`col`)
AGAINST ('szó1, szó2 szó3') FROM `table`;

És ezzel még nem értünk a végére a FULLTEXT által nyújtott lehetőségeknek, mivel egy kereső nyelvet is a rendelkezésünkre bocsát megfelelő paraméterezés mellett:

SELECT * FROM `table` WHERE MATCH (`col`)
AGAINST ('+szó1 "valami kifejezés" <szó2' IN BOOLEAN MODE)

Megpróbáltam elég sok ilyen kis módosító izét belesűríteni magába a példába is, de nézzük akkor, hogy miket is lehet használni a keresőkifejezés összeállítása során:

szó
Ha mindenféle operátor nélkül szerepel egy szó a kifejezésben, akkor az azt jelenti, hogy bár a szó jelenléte a találatban nem kötelező, de ha benne van, akkor az a sor nagyobb értékelést kap.
~szó
Ha a szó benne van a találati sorban, akkor a sor értékelése csökken.
+szó
A szónak kötelezően benne kell lennie a talált sorban.
-szó
A szó nem lehet benne a talált sorban.
<szó és >szó
A szó súlyát tudjuk állítgatni vele a kifejezésen belül (az adott sor értékét valamennyivel többel vagy kevesebbel növeli, mintha csak simán "szó"-t írtunk volna).
"valami kifejezés"
Az idézőjelek közti kifejezés szó szerint lesz véve, nem lesznek benne értelmezve a különböző operátorok és nem is szavak listájaként kerülnek feldolgozásra. Tehát a "valami kifejezés" nem fog illeszkedni a "valami, kifejezés" stringre.
*
A szokásos wildcard operátor.
( és )
A kifejezések zárójelezésére lehet használni.

Az IN BOOLEAN MODE helyére még irhatnánk azt, hogy WITH QUERY EXPANSION. Ez esetben a feldolgozása ugyanúgy történne mint az első esetben, viszont nem súlyozott sorrendet kapnánk vissza, hanem az eredetit (egyébként az ORDER BY természetesen felülbírálja a súlyozott sorrendet is). Ja, és hogy hogyan is lehet ilyen FULLTEXT indexeket készíteni? Ugyanúgy, ahogy a többi fajta indexet is:

CREATE TABLE `table` (
    `id` INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `col` VARCHAR(200),
    FULLTEXT (`col`)
);

Persze vannak a dolognak megkötései is. Csak CHAR, VARCHAR, TEXT mezőkre használhatunk FULLTEXT indexet, emellett a tábla típusa csak MyISAM lehet. A MATCH után szereplő oszloplista mind FULLTEXT indexű kell, hogy legyen, kivéve ha az IN BOOLEAN MODE be van kapcsolva, ez esetben nem kötelező, viszont cserébe jóval lassabb lesz. Ennyi lenne dióhéjban, akik mélyebb ismeretséget szeretne kötni ezzel az index típussal, azoknak tudom ajánlani a következő linkeket:

Hozzáfűznél valamit?

Dobj egy emailt a blog kukac deadlime pont hu címre.

Feliratkoznál?

Az RSS feed-et ajánljuk, ha kedveled a régi jó dolgokat.