MySQL Full-text Search
 
bl4ckb1rd 17. jan 2011 13:22:12 Pridružen od:
18. avg 2008
1122 objav
750 91 11
#1

Opis baze:

Imam več tabel, vsaka posebej ima par kolumn, in recimo v posamezni tabeli je na določene kolumne dodan index fulltext in sicer vsak posebej. Recimo: tabela: avtor, fulltext index na 'ime' in fulltext index na 'priimek'. torej, kaj želim je v bistvu tale krača:


SELECT vsebina.id, avtor.ime, avtor.priimek, beseda.naziv, podnaslov.podnaslov, MATCH(vsebina.besedilo,avtor.ime,avtor.priimek,podnaslov.podnaslov,beseda.naziv) AGAINST('podeželje') AS score FROM
`delo_vsebina` LEFT JOIN `vsebina` ON delo_vsebina.vsebina_id=vsebina.id LEFT JOIN `delo` ON delo_vsebina.delo_id=delo.id LEFT JOIN delo_avtor ON delo_avtor.delo_id=delo.id LEFT JOIN avtor ON
delo_avtor.avtor_id=avtor.id LEFT JOIN delo_beseda ON delo_beseda.delo_id=delo.id LEFT JOIN beseda ON delo_beseda.beseda_id=beseda.id LEFT JOIN delo_podnaslov ON delo_podnaslov.delo_id=delo.id LEFT
JOIN podnaslov ON delo_podnaslov.podnaslov_id=podnaslov.id WHERE MATCH(vsebina.besedilo,avtor.ime,avtor.priimek,podnaslov.podnaslov,beseda.naziv) AGAINST('podeželje')

Ni lepa, vendar bi morala delovati.



vsebina.besedilo, avtor.ime itd. (vsi v MATCH) imajo FULLTEXT index v posamezni tabeli.

Je tole sploh pravilen način iskanja, ali bi moral narediti kako temporary tabelo z rezultati le te, pa potem tam nastaviti indexe na pravilne kolumne in nato pognati search nad tisto tabelo?



Skratka error dobim: "#1210 - Incorrect arguments to MATCH"



Sem tudi repairal tabele, če bi slučajno bil to problem, vendar je napaka še vedno tu...



Zanimivo da recimo če dam pa 1 argument MATCH-u, recimo samo "avtor.ime" ali samo "vsebina.besedilo", pa SQL spelje...


všeč(0) ni všeč(0) spam(0)
blackbird.si - Moj plac za odlaganje problemov in rešitev...
 
bl4ckb1rd 17. jan 2011 13:26:44 Pridružen od:
18. avg 2008
1122 objav
750 91 11
#2

Alternativa temu bi bila pač da MATCH pošljem samo čez (vsebina.besedilo) in potem delam naprej OR LIKE ('%keyword%')nad ostalimi kolumni... vendar če se le da, ne bi tega počel.


všeč(0) ni všeč(0) spam(0)
blackbird.si - Moj plac za odlaganje problemov in rešitev...
 
Vini 17. jan 2011 13:43:05 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#3

Ne bo delovalo na tak način, ki ga poskušaš, fulltext search lahko izvajaš le po podatkih v eni tabeli.


všeč(1) ni všeč(0) spam(0)
 
bl4ckb1rd 17. jan 2011 14:51:42 Pridružen od:
18. avg 2008
1122 objav
750 91 11
#4

Varjanta je, da delaš potem MATCH (vsebina.besedilo) OR MATCH (avtor.ime) OR ... ampak potem sem uporabil kar LIKE, ker načeloma je tako... score je važen nenazadnje le ob številu pojavitev v besedilu, če pa je beseda kjerkoli drugje najdena pa predvidevam da je to direkten zadetek (se pravi če je bilo iskanje po avtorju in je nekdo vpisal ime avtorja za iskanje) in je takoj rezultat 100%. Me pa malce skrbi, kako bo tale query delal, ko bom imel za 10 let dokumentov od fakultete importanih... Verjetno bo le čas pokazal in EXPLAIN :) Hvala za odgovor.


všeč(0) ni všeč(0) spam(0)
blackbird.si - Moj plac za odlaganje problemov in rešitev...
 
Vini 17. jan 2011 15:19:31 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#5

Ojej, ne uporabljaj LIKE za te zadeve, ti lahko že kar zdaj povem kar ti bo povedal EXPLAIN, nič dobrega :) Za search lahko poskusiš uporabiti Sphinx, super zadevica.


všeč(2) ni všeč(0) spam(0)
 
Roky 17. jan 2011 18:54:00 Pridružen od:
9. apr 2008
2506 objav
3240 335 107
#6

Za začetek je hitrejš "narejen" tudi Zend Lucene, ne super ampak fajn zadevca.


všeč(0) ni všeč(0) spam(0)
rok.meglic@gmail.com - 031 492 148
 
bl4ckb1rd 18. jan 2011 09:03:03 Pridružen od:
18. avg 2008
1122 objav
750 91 11
#7

@Vini: ko si omenjal da naj ne bi naredil z LIKE-om sem mislil da bi naredil še vedno MATCH po tabeli ki ima besedila, se pravi "vsebina", katere je in bo največ, le za ostale manjše tabelice naj bi uporabil LIKE... primer kako sem naredil zaenkrat:


$addon = "SELECT DISTINCT vsebina.id, MATCH(vsebina.besedilo) AGAINST('".$keyword."') AS score FROM `delo_vsebina` LEFT JOIN `vsebina` ON delo_vsebina.vsebina_id=vsebina.id LEFT JOIN `delo` ON delo_vsebina.delo_id=delo.id LEFT JOIN delo_avtor ON delo_avtor.delo_id=delo.id LEFT JOIN avtor ON delo_avtor.avtor_id=avtor.id LEFT JOIN delo_beseda ON delo_beseda.delo_id=delo.id LEFT JOIN beseda ON delo_beseda.beseda_id=beseda.id LEFT JOIN delo_podnaslov ON delo_podnaslov.delo_id=delo.id LEFT JOIN podnaslov ON delo_podnaslov.podnaslov_id=podnaslov.id WHERE CONCAT_WS(' ', avtor.ime, avtor.priimek, beseda.naziv, podnaslov.podnaslov) LIKE ('%".$keyword."%') OR MATCH(vsebina.besedilo) AGAINST('".$keyword."')";

Še vedno misliš da bo obupen performance tega SQL-a?



Vsekakor pa vem da bo potrebno "search" spremeniti v prihodnosti in uporabiti nekaj drugega kot MySQL-ov search... SphinX sem že gledal in je precej luštna zadeva, ki sama kešira v fajlih, dejansko pa se v sintakso le-tega še nisem imel časa poglobiti.



@Roky: Trenutna aplikacija je v codeigniterju, tako da za menjavo frameworka je malce prepozno :) Predvsem zato ker je že čisto zaključena, časa pa je samo še ta teden... :)


všeč(0) ni všeč(0) spam(0)
blackbird.si - Moj plac za odlaganje problemov in rešitev...
 
Vini 18. jan 2011 09:13:12 Pridružen od:
1. sep 2006
6612 objav
5234 611 56
#8

bl4ckb1rd, če podatke prej dovolj dobro optimizirano sfiltriraš, da potem LIKE delaš le preko manjših result setov, potem bi mogoče še nekako zneslo. Ker pa ti med pogoje postavljaš OR, pa nisi nič kaj dosti dosegel. Poskusi, napolni bazo s čim več dummy teksta, pa poglej, kako dolgo se ti izvaja query. Mislim, da vsekakor predolgo, ubil si boš strežnik :)


všeč(1) ni všeč(0) spam(0)
 
Roky 18. jan 2011 09:26:27 Pridružen od:
9. apr 2008
2506 objav
3240 335 107
#9

@bl4ckb1rd, menjava framework-a ni potrebna. V codeignator dodaš helper, class, model ... karkol, kjer rečeš:


// indexer se zna obesit zato k ma premal rama, dajmo mu ga več
set_time_limit(60);
ini_set('memory_limit','64M');

require_once 'Zend/Search/Lucene.php';

$indexDir = 'pot/do/indexa';
try {
$index = Zend_Search_Lucene::open($indexDir);
$this->setIndex($index);
} catch (Exception $e) {
$this->setIndex();
}

Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive());

//RM: Just to be 100% sure that UTF-8 encoding is used
Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('UTF-8');
$query = Zend_Search_Lucene_Search_QueryParser::parse($q, 'UTF-8');
$hits = $this->getIndex()->find($query, 'area', SORT_STRING, 'score', SORT_NUMERIC, SORT_DESC);

foreach($hits as $hit) {
if (!$this->filterHit($hit)) continue;
$i++;
;

$rHits[] = array(
'area'=>$hit->area,
'title'=>$hit->title,
'url'=>$hit->url,
'full_url'=>$this->getFullUrl($hit),
'description'=> $hit->description,
'score'=>sprintf("%01.1f",$hit->score*100)
);
}
všeč(5) ni všeč(0) spam(0)
rok.meglic@gmail.com - 031 492 148
 
bl4ckb1rd 18. jan 2011 10:18:14 Pridružen od:
18. avg 2008
1122 objav
750 91 11
#10

Najlepša hvala za tele response, več kot pomagalo bo. Verjetno bom uporabil kar Lucene, glede na to da mi je Roky že namignil dejansko kako naj bi izgledalo, super res. Prišparali ste mi precej časa in dela.


všeč(0) ni všeč(0) spam(0)
blackbird.si - Moj plac za odlaganje problemov in rešitev...
 
 

🔒 Za odgovor na to temo se moraš prijaviti.

Prijavi se