ugrás a tartalomhoz

Mysql: Effektív keresés címkékkben, és szöveges mezőkben.

therest · 2012. Ápr. 11. (Sze), 11.18
Tudom, hogy ez elég mély téma, de egy alapvető irányvonalat biztosan tudtok adni.
Van egy adatbázis, három tábla:
- products (id,name,title,info,description)
- labels (id,name)
- pl (id,pid,lid)

A products táblában, több szöveges mező van varchar, és text is.
A labels táblában pedig varchar a name.
A pl tábla kapcsolja össze a címkéket a termékekkel.

És erre kellene ráengedni egy keresést, ami keres a products tábla name, title, info, és description mezőiben, és a kapcsolt címkékben is.
A hab a tortán, hogy több szó is szerepelhet a keresésben.
Illetve kellene rangsorolni is a találatokat.

Persze megírni megtudtam az alapot, úgy, hogy keresőkifejezésenként egy query, ami like %kif% -el végignézi a fent említett mezőket. Aztán phpben az eredményben levő id-ket egy asszociatív tömb indexének használom, és a számosságot rendelem hozzá értékként.
Valahogy így minden queryre:

while($record=mysql_fetch_object($result)) {
if(!isset($counts[$record->id]))
$counts[$record->id]=1;
else
$counts[$record->id]++;
}
Az összes query után a counts tömbben megvan hogy melyik id-t találtam meg legtöbbször, és így előáll a rangsor.

Működni működik csak gondolom elég béna, biztosan van valami stílusos kód erre. Olyan megoldást keresnék ami effektív, bevált.
A másik terület a címkék kérdése, ezeket is vizsgálni kéne a keresőkifejezésekre, de erről fogalmam sincs hogyan. Arra gondoltam, hogy valami sztringgé kéne fűzni őket még mysql-en belül (az adott product id-hez tartozókat), és azon keresni like %kif% -al, csak a módszer amivel ezt elérhetném kérdés előttem teljesen.

Előre is kösz!
 
1

Indexek

Poetro · 2012. Ápr. 11. (Sze), 11.35
Lehet építeni előre mindenféle indexeket, amik egyszerűsítik ezt a keresést. Azaz például tartalmazza az összes szót, és hogy az a dokumentumban a csatolt címkékkel együtt hányszor fordul elő, illetve a címkékkel lehetne súlyozni az előfordulást is. Azaz ha egy szó egyszer fordul elő a címben, az 2 pont, kétszer a tartalomban az még két pont, és van egy címke rajta ugyanezzel a szóval az mondjuk még 5 pont. Így szavanként lenne egy keresési index, ami megmondja, hogy az aktuális szóra a tartalomnak hány pontja van. De természetesen léteznek más metódusok is, és amennyiben hatékony akarsz lenni, akkor egy külső keresőmotort használsz a szabadszavas keresésre, mint amilyen az Apache Solr illetve a Sphinx, és ezek API-ját kötöd be az alkalmazásodba. De csak ha tényleg hatékony akarsz lenni.
2

A címkével súlyozás jó ötlet!

therest · 2012. Ápr. 11. (Sze), 12.00
A címkével súlyozás jó ötlet! A gondom az, hogy gőzöm sincs, hogy egy külön indexet hogyan kellene megépíteni, főleg az összes szóból. Elég rémisztőnek hangzik! :) Hol kellene ennek nekikezdeni a fenti struktúra esetén?

A hatékonyság egyelőre annyit tesz, hogy 1000 termékre és kb. 100-200 címkére jól kell menjen a keresés (az a pl táblában már meglepően sok sort jelenthet). Amiket linkeltél meg fogom nézni, de a jelenlegi munkám végéig tuti nem lesz elég időm arra, hogy megismerjem, integráljam.
3

Felbontod

Poetro · 2012. Ápr. 11. (Sze), 12.14
Létrehozol pár táblát. Az egyikben tárolod a szavakat (szavak tábla), a másikban pedig a szó kulcsát a súlyozott értékét és a tartalom kulcsát (szoindex tábla). Így összesen két táblád lesz. Az szavak-ból kikeresed a szó kulcsát, majd ha létezik, akkor keresel az index táblában, és a súly szerint rendezel. Az indexelést csinálhatod mondjuk 10 tartalmanként, vagy amikor a tartalmat elmentik.

Természetesen ennél lehet sokkal bonyolultabb rendszert csinálni. Talán érdemes lehet megnézni, hogy az általad használt keretrendszerben / CMS-ben van-e ilyen szolgáltatás, illetve ha nincs, akkor megnézni egyet, amiben van. Például a Drupal 6-ban egy elég egyszerű, de viszonylag hatékony rendszer van. Ennek indexelési metódusát talán érdemes átnézni.
4

Ez most kicsit magas nekem.

therest · 2012. Ápr. 11. (Sze), 13.06
Ez most kicsit magas nekem. :)
Akkor ez azt jelentené, hogy egy termék felvitelekor, valahogy az új termék összes szavát ezekben a táblákban el kell helyezni. Ez már alapból elég félelmetesen hangzik.
5

Félelmetes?

Poetro · 2012. Ápr. 11. (Sze), 13.16
Ez miért hangzik félelmetesen? Az a kérdés, hogy hatékonyan akarsz-e keresni, vagy egyszerűen? Mert a MySQL full-text search is hasonló alapokon nyugszik, csak az a háttérben csinál hasonló indexelést.
6

Az előbb írt számok számok

therest · 2012. Ápr. 11. (Sze), 13.32
Az előbb írt számok számok (1000 termék, 100-200 címke) jellemzik a rendszert. Egy terméknél, két kb 100 karakter hosszú varchar, és két text mező van.
Ami ezt ki tudja szolgálni sebességben az nekem már elég lenne. Szerinted ekkora méreteknél mi állná meg a helyét?

Félelmetesen azért hangzik, mert szorít az idő, és én balga azt hittem, hogy van olyan keresés, ami hatékony és egyszerű egyszerre. :)
7

Nem sok

Poetro · 2012. Ápr. 11. (Sze), 13.38
Ez az adatmennyiség nem tűnik soknak. Én már több GB-os adatbázisokkal is dolgoztam, MySQL-ben is.
8

Elmerülök a mysql-es

therest · 2012. Ápr. 11. (Sze), 13.43
Elmerülök a mysql-es full-text-es doksiban, köszi a linket. Egyelőre ez olyasminek tűnik amit még időben meg tudok érteni, és felhasználni.
9

Eddig a MATCH - AGAINST

therest · 2012. Ápr. 11. (Sze), 14.42
Eddig a MATCH - AGAINST használatát olvasom, de úgy tűnik, hogy itt van valami 50%-os elhagyási ráta.
Jól értem, hogy ha az adott szóra kapott sorok száma eléri az táblában lévő sorok számának felét, akkor "stopword" lesz, és nem vesz részt az eredmény generálásában?
Tehát ha van egy két soros adatbázisom, 'alma' és 'körte' értekkel az adott oszlopban, akkor se almára, se körtére nem kapok eredményt? Mi ennek az értelme akkor?

A BOOLEAN MODE pedig kikapcsolja ezt, csak akkor meg nincs rangsorlás, és lassabb.
A fentieken túl még a címkéket is be kéne vonni a buliba.