Reputation: 440
I have a search bar on a website which I was doing a wildcard search against a word across a 2 tables and 4 columns. I want to do a multiple word search so I have swapped the coding over to a match..against statement.
The issue I have is ordering the relevance. At the moment if I search for 3 words I would like it to display the products with those 3 words in first but it seems to display the 3rd word in priority over the 2nd then the 3rd. Not sure if this is due to such a wide search (column-wise) or whether I need to associate the relevance per column.
I have added boolean mode and changed Spaces in the search string with the greater than sign to try and add priority..
I am using prepared statement with PDO for maximum security..(i Hope)
My current code..
$search = filter_var($_GET['s'], FILTER_SANITIZE_STRING);
$searchfor = str_replace(' ',' >',$searchfor);
$itemResults = $conn->prepare("SELECT a.*
FROM item_info_short a
LEFT JOIN item_information b
ON a.id = b.id
WHERE MATCH(a.title,a.manufacturer,a.item_code,a.colour,b.shortdescription)
AGAINST(:searchfor IN BOOLEAN MODE)
LIMIT $offset,$itemsperpage");
$itemResults->bindValue(':searchfor',$searchfor,PDO::PARAM_STR);
$itemResults->execute();
Upvotes: 2
Views: 2274
Reputation: 116110
Normally you would always need ORDER BY to ensure a certain ordering, but MySQL adds some magic to the natural language matching, that causes rows to always be ordered by relevance. Unfortunately for you, this doesn't apply to boolean searches.
http://dev.mysql.com/doc/refman/5.5/en/fulltext-boolean.html says:
Boolean full-text searches have these characteristics:
So instead of using a boolean search, you could do a natural language search, or use that other search to order the results by:
SELECT a.*
FROM item_info_short a
LEFT JOIN item_information b ON a.id = b.id
WHERE
MATCH(a.title,a.manufacturer,a.item_code,a.colour,b.shortdescription)
AGAINST(:searchfor IN BOOLEAN MODE)
ORDER BY
MATCH(a.title,a.manufacturer,a.item_code,a.colour,b.shortdescription)
AGAINST(:searchfor IN NATURAL LANGUAGE MODE) DESC
LIMIT $offset,$itemsperpage");
Or, possibly better/faster:
SELECT a.*
FROM item_info_short a
LEFT JOIN item_information b ON a.id = b.id
WHERE
MATCH(a.title,a.manufacturer,a.item_code,a.colour,b.shortdescription)
AGAINST(:searchfor IN NATURAL LANGUAGE MODE) DESC
LIMIT $offset,$itemsperpage");
Upvotes: 1