Autor | Zpráva | ||
---|---|---|---|
ROLAND Profil * |
#1 · Zasláno: 16. 3. 2015, 18:45:33
Dobrá den,
snažím se vytvořit fulltextové vyhledávání v databázi, resp. ve výpisu, který vznikl spojením tabulek. Když použiju to co jsem prozatím vytvořil, tak mi každý záznam vypíše několikrát - pokaždý s jiným garantem, s jinou licencí a s jiným typem. Tak dostanu místo asi 100 záznamů, přes 3000 záznamů. Zkoušel jsem využít nějký GROUP BY, ale u každého záznamu mi to tentokrát napíše první záznam z tabulek garant, typ a licence. Posím o jakoukoliv radu. Děkuji $sql="SELECT data.id_data, data.nazevdat, data.reprezentace, data.meritko, data.nahled, data.ukazkaodkaz, data.popis, data.popis2, data.poskytovani, data.prispevatel, data.format, garant.nazev, data.historie, data.souradsystem, typ.typ, licence.typlicence, data.data_link, data.znalost FROM data, typ, garant, licence WHERE data.id_garant=garant.id_garant AND data.id_typ=typ.id_typ AND data.id_licence=licence.id_licence AND MATCH (data.nazevdat) AGAINST ('".$_GET['search']."' IN BOOLEAN MODE) OR MATCH (data.meritko) AGAINST ('".$_GET['search']."' IN BOOLEAN MODE) OR MATCH (data.ukazkaodkaz) AGAINST ('".$_GET['search']."' IN BOOLEAN MODE) OR MATCH (data.poskytovani) AGAINST ('".$_GET['search']."' IN BOOLEAN MODE) OR MATCH (data.prispevatel) AGAINST ('".$_GET['search']."' IN BOOLEAN MODE) OR MATCH (data.historie) AGAINST ('".$_GET['search']."' IN BOOLEAN MODE) OR MATCH (data.popis) AGAINST ('".$_GET['search']."' IN BOOLEAN MODE) OR MATCH (data.popis2) AGAINST ('".$_GET['search']."' IN BOOLEAN MODE) OR MATCH (data.souradsystem) AGAINST ('".$_GET['search']."' IN BOOLEAN MODE) OR MATCH (data.format) AGAINST ('".$_GET['search']."' IN BOOLEAN MODE) OR MATCH (data.data_link) AGAINST ('".$_GET['search']."' IN BOOLEAN MODE) OR MATCH (data.znalost) AGAINST ('".$_GET['search']."' IN BOOLEAN MODE) ORDER BY data.id_data ASC"; $result=mysqli_query($conn, $sql); |
||
Keeehi Profil |
#2 · Zasláno: 16. 3. 2015, 19:20:12
1) Pro spojování tabulek bych nepoužíval cross join, vytváří to opravdu gigantické tabulky, které se pak filtrují. Možná se na to použije nějaká optimalizace, ale nespoléhla bych na to.
Proto FROM data, typ, garant, licence WHERE data.id_garant=garant.id_garant AND data.id_typ=typ.id_typ AND data.id_licence=licence.id_licence FROM data JOIN typ USING (id_typ) JOIN garant USING (id_garant) JOIN licence USING (id_licence) WHERE ... 2) Víte, že do MATCH můžete zadat místo jednoho sloupce i celý seznam sloupců,které se mají prohledávat? Jelikož hledáte pořád stejný výraz, tak to zkrátí dotaz. Teoreticky by to mohlo býti rychlejší. 3) To, proč to vypisuje 3000 řádků je kombinace cross joinu a chyby v WHERE. Problém je v tom, že všechny to MATCHe spojené ORem by měly být obalené v závorce, protože pak stačí aby jeden z nich byl pravdivý a pak je jedno, co bylo v těch prvních třech pravidlech. WHERE 1 AND 0 AND 1 OR 1 OR 1 => true WHERE 1 AND 0 AND (1 OR 1 OR 1) => false |
||
ROLAND Profil * |
#3 · Zasláno: 16. 3. 2015, 19:54:14 · Upravil/a: ROLAND
Tak jsem vše udělal podle prvního a druhého kroku a stále mám problém. Tentokrát jsem zkusil provést SQL dotaz přímo v databázi a napíše mi to:
Can't find FULLTEXT index matching the column list. Příčemž všechny sloupce z dotazu mám daný jako FULLTEXT klíč. Co s tím? jen doplnění používám úložiště innoDB. |
||
Keeehi Profil |
Can't find FULLTEXT index matching the column list.
To souvisí s tím, že máš fulltext vytvořený pro každý sloupec a ne přes celý set. Nevím, zda to má nějaké nevýhody, nejsem v tom odborník. Kajman_ by asi vědel lépe. Jestli to stále zobrazuje více řádků než má, mohl bys vytvořit ukázku? Nechat 2-3 řádky v tabulkách, ukázat dotaz a výsledek, v kterém budou vidět ty řádky navíc. |
||
ROLAND Profil * |
#5 · Zasláno: 16. 3. 2015, 20:16:04
Už to neukazuje více řádků. Ukazuje mi to chyby:
Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given in C:\web\search_sc.php on line 28 Počet záznamů: line 28: echo "Počet záznamů: ".mysqli_num_rows($result);
A Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given in C:\web\search_sc.php on line 31 line 31: if (mysqli_num_rows($result)>0) { echo "<div class='table'>"; echo "<table border=1>"; .... |
||
Keeehi Profil |
#6 · Zasláno: 16. 3. 2015, 20:36:20
Z dokumentace mysqli_query():
„Return Values Returns FALSE on failure“ Tudíž bych si vypsal mysqli_error($link);
|
||
ROLAND Profil * |
#7 · Zasláno: 16. 3. 2015, 20:59:54
po vypsání mysqli_error se objeví opět hláška: Can't find FULLTEXT index matching the column list
|
||
Kubo2 Profil |
#8 · Zasláno: 16. 3. 2015, 21:02:15
ROLAND:
A máš vytvorený FULLTEXT KEY cez všetky stĺpce v rovnakom poradí, aké používaš v dotaze?
|
||
Keeehi Profil |
#9 · Zasláno: 16. 3. 2015, 21:02:27
OK, tak znovu:
„To souvisí s tím, že máš fulltext vytvořený pro každý sloupec a ne přes celý set.“ |
||
ROLAND Profil * |
#10 · Zasláno: 16. 3. 2015, 21:13:25
Kubo2
Mám vytvořený klíč ve všech sloupcích z dotazu a ve stejném pořadí. Keeehi: A nevíš jak to vytvořím přes celý set? Dával jsem to ručně ke každému sloupci co potřebuju. |
||
Keeehi Profil |
#11 · Zasláno: 16. 3. 2015, 21:29:35
ROLAND:
„Mám vytvořený klíč ve všech sloupcích z dotazu a ve stejném pořadí.“ n klíčů je něco jiného než jeden klíč přes n sloupců CREATE FULLTEXT INDEX idx ON data(nazevdat, meritko, ukazkaodkaz, ...); |
||
ROLAND Profil * |
#12 · Zasláno: 16. 3. 2015, 21:48:20
Toto mi už teda funguje. Jen poslední dotaz, když chci takto vytvořit index společně pro záznamy z jiné tabulky, které se tahají co hlavní přes cizí klíč - například vyhledávat jméno garanta který je v hlavní tabulce označen pouze pomocí ID. Mám za toto
CREATE FULLTEXT INDEX idx ON data(nazevdat, meritko, ukazkaodkaz, ...) AND garant(nazev) ?
Nebo jakým způsobem toto dát celé dohromody? |
||
Keeehi Profil |
#13 · Zasláno: 16. 3. 2015, 22:23:18
ROLAND:
Index lze vytvářet přeci jen na jednou tabulkou. Když budeš potřebovat vyhledávat ve více tabulkách, tak budeš muset spojit více MATCHů ORem, ale sloupce z jedné tabulky mohou být v jedné klauzuli MATCH. Jestli s tím máš ale problémy, tak to nechej jak to je a vyhledávej nad jednotlivými sloupci. Použij ten nový join s stará pravidla match z where. Jelikož kvůli novému joinu tam nebudou ty první 3 logické výrazy a zbydou tedy jen ORy, nebude problém s prioritou operátorů. |
||
ROLAND Profil * |
#14 · Zasláno: 16. 3. 2015, 22:38:48
Všechno vyřešeno a funguje to jak tpotřebuju. Moc děkuji za pomoc a omlouvám se za hloupé dotazy, ale jsem naprostý začátečník.
|
||
Kajman Profil |
#15 · Zasláno: 17. 3. 2015, 07:46:21
Jen pozor na to, že fulltext funguje na innodb až od verze 5.6.4, vybírejte si tedy hosting, co má novější verzi mysql a bude tuto kombinaci podporovat.
A ještě poznámka, že v boolean mode na myisam není potřeba fulltextový index, ale rychlost není taková jako s připraveným indexem. |
||
Časová prodleva: 9 let
|
0