Reputation: 246
I'm trying to mod a search routing, i have two fields, artist & title, when i search for example Foo Fighters the pretender, i don't get any results, whereas if i search individually i do. Any help would be much appreciated thanks.
$arraySearch = explode(" ", $searchvalue);
$arrayFields = array(0 => "Artist", 1 => "Title");
$countSearch = count($arraySearch);
$a = 0;
$b = 0;
$query = "SELECT * FROM ".$table." WHERE (";
$countFields = count($arrayFields);
while ($a < $countFields)
{
while ($b < $countSearch)
{
$query = $query."$arrayFields[$a] LIKE '%$arraySearch[$b]%'";
$b++;
if ($b < $countSearch)
{
$query = $query." AND ";
}
}
$b = 0;
$a++;
if ($a < $countFields)
{
$query = $query.") OR (";
}
}
$query = $query.")";
$query_result = mysql_query($query);
echo '<h1>Your Search Results</h1>'."\n\n";
if(mysql_num_rows($query_result) < 1)
{
echo '<p>No matches found for "'.$searchvalue.'"</p>';
}
else
{
echo '<p>Search Results for "'.$searchvalue.'":</p>'."\n\n";
while($row = mysql_fetch_assoc($query_result))
{
// output
}
}
Upvotes: 1
Views: 831
Reputation: 69977
This search function is very inefficient. Since you are searching on a wildcard %blah%
, it has to do a full table scan to find any records. That is, if you have 1 million records, it has to read all 1 million records in order to find your search results. On a busy site with a large table, this can kill your performance and database server.
If you are using the MyISAM engine for the table, I would recommend adding a FULLTEXT index to the artist and title columns and then performing a fulltext search like this:
SELECT * FROM `table` WHERE
MATCH(`artist`, `title`)
AGAINST('foo fighters the pretender');
As written by the OP, here is a query that sorts by match relevance on the search query
$search = $db->escape('foo fighters the pretender');
$query = "SELECT *,
MATCH(Artist, Title) AGAINST('$search' IN BOOLEAN MODE) AS relevance
FROM table
WHERE
MATCH (Artist, Title)
AGAINST('$search' IN BOOLEAN MODE)
ORDER BY relevance DESC";
Upvotes: 3
Reputation: 376
After you close the parentheses of the query, put a var_dump($query) so you will understand what is happening.
eg: The following code outputs: string(123) "SELECT * FROM WHERE (Artist LIKE '%foo%' AND Artist LIKE '%fighters%') OR (Title LIKE '%foo%' AND Title LIKE '%fighters%')"
<?php
$searchvalue = 'foo fighters';
$arraySearch = explode(" ", $searchvalue);
$arrayFields = array(0 => "Artist", 1 => "Title");
$countSearch = count($arraySearch);
$a = 0;
$b = 0;
$query = "SELECT * FROM ".$table." WHERE (";
$countFields = count($arrayFields);
while ($a < $countFields)
{
while ($b < $countSearch)
{
$query = $query."$arrayFields[$a] LIKE '%$arraySearch[$b]%'";
$b++;
if ($b < $countSearch)
{
$query = $query." AND ";
}
}
$b = 0;
$a++;
if ($a < $countFields)
{
$query = $query.") OR (";
}
}
$query = $query.")";
var_dump($query);
?>
Upvotes: 0
Reputation: 12069
Change this:
$query = $query." AND ";
to this:
$query = $query." OR ";
Essentially you are saying SELECT... WHERE (field1 like 'foo%' AND field1 like 'bar%')
. You will never find a row where field1 is like both words unless they were the exact same word. Its like saying SELECT ... WHERE id=1 AND id=2
, not going to pull any results, where as SELECT ... WHERE id=1 OR id=2
will pull rows 1 and 2.
Upvotes: 1