Webisztán után szabadon:
Keresők fejlesztéséhez igen hasznos lehet a következő tipp, ami koránt sem tökéletes, de kezdetnek mindenképpen jó. Cél, hogy a juzer által begépelt keresőszót validáljuk, vélhetően elgépelés esetén keressünk egy olyant, amire felhasználónk gondolhatott (did you mean). Talán nem kell elmagyarázni, hogy ehhez egy szótárra van szükségünk, ami vagy az összes kereshető szót tartalmazza, vagy csak azokat, amire keresőnk találatot adhat. Nyilván az első lehetőséget el is vethetjük….
Jelen esetben az elv az, hogy a szótárból azokat a szavakat válasszuk ki, ami a keresendő szóval a lehető legtöbb helyen egyezik (elölről és hátulról is). Ebből ugye több is lehet, ezért rendezni kell, és a legelsőt venni. Ez lesz a feltételezett keresendő kifejezés. Nézzük meg hogy néz ez ki MySQL-ben:
Keressünk a “webdesign” szóra:
select id, szoveg,
instr(upper(left(szoveg,1)), upper(‘w’)) +
instr(upper(left(szoveg,2)), upper(‘we’)) +
instr(upper(left(szoveg,3)), upper(‘web’)) +
instr(upper(left(szoveg,4)), upper(‘webd’)) +
instr(upper(left(szoveg,5)), upper(‘webde’)) +
instr(upper(left(szoveg,6)), upper(‘webdes’)) +
instr(upper(left(szoveg,7)), upper(‘webdesi’)) +
instr(upper(left(szoveg,8)), upper(‘webdesig’)) +
instr(upper(left(szoveg,9)), upper(‘webdesign’)) +
instr(upper(right(szoveg,1)), upper(‘n’)) +
instr(upper(right(szoveg,2)), upper(‘gn’)) +
instr(upper(right(szoveg,3)), upper(‘ign’)) +
instr(upper(right(szoveg,4)), upper(‘sign’)) +
instr(upper(right(szoveg,5)), upper(‘esign’)) +
instr(upper(right(szoveg,6)), upper(‘design’)) +
instr(upper(right(szoveg,7)), upper(‘bdesign’)) +
instr(upper(right(szoveg,8)), upper(‘ebdesign’)) +
instr(upper(right(szoveg,9)), upper(‘webdesign’)) egyezik,
if (upper(szoveg)=upper(‘webdesign’),’0′,’1′) lehet,
from (select * from szotar where szoveg like ‘%w%e%’) szotar
order by egyezik desc, length(szoveg) asc limit 0,1
Mik a mezők:
egyezik: a betűegyezőségek száma, e szerint rendezünk csökkenő sorrendbe (fenti példában 18, minden egyezik)
lehet: megadja, hogy a találatunk pontosan megegyezik-e a keresett szóval: 0-igen, 1-nem (fenti példában 0)
Allekérdezésre azért van szükség, hogy sok szó esetén ne legyen olyan sok hasonlítgatás, ez elhagyható(szerverterhelés rovására), szűkíthető ízlés szerint.
Keressünk a nem létező szóra: webesign
select id, szoveg,
instr(upper(left(szoveg,1)), upper(‘w’)) +
instr(upper(left(szoveg,2)), upper(‘we’)) +
instr(upper(left(szoveg,3)), upper(‘web’)) +
instr(upper(left(szoveg,4)), upper(‘webe’)) +
instr(upper(left(szoveg,5)), upper(‘webes’)) +
instr(upper(left(szoveg,6)), upper(‘webesi’)) +
instr(upper(left(szoveg,7)), upper(‘webesig’)) +
instr(upper(left(szoveg,8)), upper(‘webesign’)) +
instr(upper(right(szoveg,1)), upper(‘n’)) +
instr(upper(right(szoveg,2)), upper(‘gn’)) +
instr(upper(right(szoveg,3)), upper(‘ign’)) +
instr(upper(right(szoveg,4)), upper(‘sign’)) +
instr(upper(right(szoveg,5)), upper(‘esign’)) +
instr(upper(right(szoveg,6)), upper(‘besign’)) +
instr(upper(right(szoveg,7)), upper(‘ebesign’)) +
instr(upper(right(szoveg,8)), upper(‘webesign’)) egyezik,
if (upper(szoveg)=upper(‘webesign’),’0′,’1′) lehet
from (select * from szotar where szoveg like ‘%w%e%’) szotar
order by egyezik desc, length(szoveg) asc limit 0,1
Talált szavak sorban:
webdesing: 8
webmagazin: 4
webcím: 3
S így tovább….
Az ismétlődő …instr(upper(left(szoveg,1)), upper(‘w’)) + … részt egy függvénnyel lehet előállítani, mezei for ciklus.
Akinek esetleg ötlete, javaslata van a tökéletesítéshez, azt szívesen fogadjuk.
regexppel nem lehetne valamit varacskolni? lehet az is jó megoldás lenne. pl. úgy összerakni a query-t, hogy olyan szavakra IS keressen, ami az eredeti szóval mittomén 60%-ban megegyezik. azaz ha egy 10 karakteres kifejezésből bármelyik 6 (tehát %hat%) külön is ad találatot. bár mondjuk az nem annyira did you mean.
ezt én úgy használom, hogy ezek a szótár szavak vannak kötve egy másik táblában lévő adatokhoz. A keresés előtt a fentieket futtatva tudom meg, hogy a keresendő szó létezik-e. Ha létezik, a következő keresés pontos találatot ad, tehát a szóhoz tartozó id-val keresek tovább. Ez ugye gyorsabb, mert nem kell táblát kapcsolni. Ha csak “hasonló” szavam van, akkor keresek arra is, meg az ajánlott szóra is, és szépen ki lehet írni, hogy ezt az inteligens rendszerünk ajánlotta, blablabla.
Sajnos a MySQL regexpje kicsit butácska, meg lassúb is lehet…
hm… nem mai, de azért egykét gondolatot.
Én is ilyesmin dolgozok, és talán érdemes megnézni az alábbiakat:
SOUNDEX – mysql-ben
levenshtein – php-ban
Az utóbbi két szó közötti távolságot adja meg.
A Levenshtein-ről bővebben itt:
http://en.wikipedia.org/wiki/Levenshtein_distance