PDO fulltext MATCH
Met dank aan een tutorial waar Arien me opgewezen heeft, (tijdje geleden al, maar kwam er nu pas echt aan toe)
Heb ik dus de tabeltype van producten tabel aangepast naar myisam en een fulltext index gemaakt op
prod_title en op prod_description
In phpmyadmin werkt het geweldig. Maar in php krijg ik helemaal niks terug.
Ik debug de query in php, en print deze op het scherm, en ziet er goed uit.
Kopieren->plakken naar SQL in phpmyadmin geeft gewoon resultaten terug.
De query is ongeveer als volgt:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
SELECT p.*,COUNT(r.rev_id) as revAmount, SUM(r.rev_score) as revTotal,h.*,m.*
FROM dnshop_products p
LEFT JOIN dnshop_reviews r ON r.rev_prod_id = p.prod_id
LEFT JOIN dnshop_highlighted h ON p.prod_id = h.hlight_prod_id
LEFT JOIN dnshop_media m ON p.prod_id = m.media_prod_id
WHERE p.prod_visible = 1
AND m.media_weight = 1
AND p.prod_price < 900
GROUP BY p.prod_id
ORDER BY MATCH(p.prod_title) AGAINST("disney") DESC,p.prod_title ASC LIMIT 0,20
FROM dnshop_products p
LEFT JOIN dnshop_reviews r ON r.rev_prod_id = p.prod_id
LEFT JOIN dnshop_highlighted h ON p.prod_id = h.hlight_prod_id
LEFT JOIN dnshop_media m ON p.prod_id = m.media_prod_id
WHERE p.prod_visible = 1
AND m.media_weight = 1
AND p.prod_price < 900
GROUP BY p.prod_id
ORDER BY MATCH(p.prod_title) AGAINST("disney") DESC,p.prod_title ASC LIMIT 0,20
Zien jullie iets verkeerds?
Mijn select functie is als volgt:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function __construct($DB_TYPE, $DB_NAME, $DB_HOST, $DB_USER, $DB_PASS) {
parent::__construct($DB_TYPE . ':host=' . $DB_HOST . ';dbname=' . $DB_NAME, $DB_USER, $DB_PASS);
}
public function select($query, $array = array(), $fetchMode = PDO::FETCH_ASSOC) {
$sth = $this->prepare($query);
foreach($array as $key => $value) {
$sth->bindValue(':' . $key, $value);
}
if($this->debug)
print_r($sth->queryString);
$sth->execute();
if($sth->rowCount() == 0) {
return false;
} else {
return $sth->fetchAll($fetchMode);
}
}
parent::__construct($DB_TYPE . ':host=' . $DB_HOST . ';dbname=' . $DB_NAME, $DB_USER, $DB_PASS);
}
public function select($query, $array = array(), $fetchMode = PDO::FETCH_ASSOC) {
$sth = $this->prepare($query);
foreach($array as $key => $value) {
$sth->bindValue(':' . $key, $value);
}
if($this->debug)
print_r($sth->queryString);
$sth->execute();
if($sth->rowCount() == 0) {
return false;
} else {
return $sth->fetchAll($fetchMode);
}
}
Ik gebruik gewoon PDO type:mysql
Gewijzigd op 16/08/2016 21:15:50 door Dennis WhoCares
- wat geeft deze methode weer als $this->debug true is?
- als je de query logt: hoe luidt de query die daadwerkelijk is uitgevoerd? dit is overigens de énige manier om duidelijkheid te krijgen wat er aan de hand is
- staat dit alles (aanroep van select()) in een try-catch blok?
- worden fouten gemeld (in het algemeen en voor PDO specifiek)? wat is de waarde van PDO::ATTR_ERRMODE? dit is standaard PDO::ERRMODE_SILENT, oftewel, er kraait dan geen haan naar opgetreden fouten
- hoe luidt de waarde van PDO::ATTR_EMULATE_PREPARES? dit is standaard true, oftewel, als er fouten optreden (die mogelijk niet gemeld worden) dan komt dit pas tot uiting bij de execute() en niet al bij prepare(), omdat ingeval je prepared statements emuleert er geen SQL-sjabloon naar de database wordt verstuurd
Quote:
Ik debug de query in php, en print deze op het scherm, en ziet er goed uit.
Kopieren->plakken naar SQL in phpmyadmin geeft gewoon resultaten terug.
Kopieren->plakken naar SQL in phpmyadmin geeft gewoon resultaten terug.
Maar dat is niet de exacte query die wordt uitgevoerd? Log dat ding, en kijk welke query er daadwerkelijk wordt uitgevoerd. Werk van daaruit terug naar je code.
de query die ik bovenaan noemde, is toch wel hetgene wat ik krijg als debug true is ;-)
Behalve dat het naast elkaar staat dan, en de price:
==
Dus wordt dan:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
$getResults = $this->model->getSearchResult('SELECT p.*,COUNT(r.rev_id) as revAmount, SUM(r.rev_score) as revTotal,h.*,m.*
FROM dnshop_products p
LEFT JOIN dnshop_reviews r ON r.rev_prod_id = p.prod_id
LEFT JOIN dnshop_highlighted h ON p.prod_id = h.hlight_prod_id
LEFT JOIN dnshop_media m ON p.prod_id = m.media_prod_id
WHERE p.prod_visible = 1
AND m.media_weight = 1
AND p.prod_price < :tPrice
GROUP BY p.prod_id
ORDER BY MATCH(p.prod_title) AGAINST("disney") DESC,p.prod_title ASC LIMIT 0,20',array('tPrice' => 900))
FROM dnshop_products p
LEFT JOIN dnshop_reviews r ON r.rev_prod_id = p.prod_id
LEFT JOIN dnshop_highlighted h ON p.prod_id = h.hlight_prod_id
LEFT JOIN dnshop_media m ON p.prod_id = m.media_prod_id
WHERE p.prod_visible = 1
AND m.media_weight = 1
AND p.prod_price < :tPrice
GROUP BY p.prod_id
ORDER BY MATCH(p.prod_title) AGAINST("disney") DESC,p.prod_title ASC LIMIT 0,20',array('tPrice' => 900))
Hoewel ik de bindValue al weg gehaald had en alles static in de query gezet heb.
Ik zal vanavond de ERRMODE_EXCEPTION eens instellen en eventueel de try blok proberen, misschien dat ik dan foutmeldingen krijg? En waarschijnlijk zelf wel uitkom, anders kan ik hier duidelijkere informatie geven.
Momenteel zijn geen fouten, maar gewoon lege result.
Hoewel dat waarschijnlijk komt door:
Code (php)
1
2
3
4
5
2
3
4
5
if($sth->rowCount() == 0) {
return false;
} else {
return $sth->fetchAll($fetchMode);
}
return false;
} else {
return $sth->fetchAll($fetchMode);
}
Toevoeging op 17/08/2016 20:34:40:
kom er nou achter, dat blijkbaar de vps er zin in had om een backup terug te zetten..
of moet ik de FULLTEXT INDEX () elke keer weer toevoegen als ik ga zoeken?
Toevoeging op 17/08/2016 21:06:06:
Ik wil ook graag op partials zoeken.
Bijv. 5 punt
Moet ik resultaten krijgen zoals 5 puntsgordel
Nou zag ik dat dit ALLEEN kan met, MATCH (field) AGAINST ('*5*punt*' AS BOOLEAN)
(als voorbeeld), maar dan is de MATCH natuurlijk 0 of 1. Dus is er weinig te sorteren op daadwerkelijke 'match score'
Is hier een oplossing voor ?
Als je een aggregatie functie (zoals count, sum, avg etc) gebruikt, moeten ALLE andere kolommen in GROUP BY staan.
Ik zie in jouw query p.*, h.* en m.* staan, maar je groupt alleen op p.prod_id....
http://wiki.pfz.nl/group-by
In principe hoor je daar een foutmelding op te krijgen.
deze opmerking heb ik al eens eerder gehad geloof ik.
Suggereer je dat ik
moet doen ? Momenteel met vele producten, meerdere media en de hlight is maar een enkele record p product (als die er uberhaubt is(de hlight))
Dan nog zit ik met partial match, waar ik problemen mee heb.
Is daar een oplossing voor?
als je SELECT * FROM adres
doet
en adres bevat adres_id, naam, straat, postcode
dan hoort er bij
SELECT count(1), adres.* FROM adres
dus GROUP BY adres_id, naam, straat, postcode
Daarom is het gebruik van * in combinatie met een aggregatie functie niet zo'n goed idee.
Ook al omdat een tabel best kan worden aangepast. Stel iemand bedenkt dat de kolom Land ook wel handig is in je adres. Dan zou je die moeten toevoegen, terwijl je dat land mogelijk helemaal niet nodig hebt bij die query.
Ivo P op 18/08/2016 11:38:20:
je moet strikt genomen ALLE kolommen noemen.
als je SELECT * FROM adres
doet
en adres bevat adres_id, naam, straat, postcode
dan hoort er bij
SELECT count(1), adres.* FROM adres
dus GROUP BY adres_id, naam, straat, postcode
Daarom is het gebruik van * in combinatie met een aggregatie functie niet zo'n goed idee.
Ook al omdat een tabel best kan worden aangepast. Stel iemand bedenkt dat de kolom Land ook wel handig is in je adres. Dan zou je die moeten toevoegen, terwijl je dat land mogelijk helemaal niet nodig hebt bij die query.
als je SELECT * FROM adres
doet
en adres bevat adres_id, naam, straat, postcode
dan hoort er bij
SELECT count(1), adres.* FROM adres
dus GROUP BY adres_id, naam, straat, postcode
Daarom is het gebruik van * in combinatie met een aggregatie functie niet zo'n goed idee.
Ook al omdat een tabel best kan worden aangepast. Stel iemand bedenkt dat de kolom Land ook wel handig is in je adres. Dan zou je die moeten toevoegen, terwijl je dat land mogelijk helemaal niet nodig hebt bij die query.
Jeetje, wordt dan wel een gigantische query -.- als ik ALLE 'SELECT' velden moet opgeven.
Zijn er bekende problemen, als je dit niet doet ?
Momenteel werkt alles nog altijd naar behoren in de huidige situatie.
Bij http://www.pfz.nl/wiki/group-by/#maar-dat-hoeft-toch-niet-altijd
staat een voorbeeld hoe het resultaat er keurig uitziet.
Klopt weliswaar niets van, maar je krijgt een resultaat.
De tabel media, kan meerdere records hebben op 1 prod_id, maar highlight max. 1
De media heb ik al gevangen door media_weight = 1 te geven.
Dus ik ben niet bang dat ik ooit meerdere records krijg.