我正在尝试从用户在MySQL表中输入的标签中搜索关键字,并根据匹配数返回最佳结果。
代码:
MySQL结构:
id | keywords | phrase
1 | apple king pearl | I was eating an apple when the king hit me
2 | brush brute fancy | you fancy this brush?
3 | king queen kingdom | shall the queen obey the king or the kingdom?
PHP:
$keywords_raw='me wall like king apple' //define keywords based on the tags the user inputs
$keywords=explode(' ', $keywords_raw);
.... 这就是我被卡住的地方。我的意见是:
将对每个关键字执行搜索,例如“我”,“墙”,“喜欢”等等
对于每个关键字,它将在表的每一行中搜索“keywords”和“phrase”两列,并返回找到的匹配数。例如,搜索针对第一行输入的关键字将返回关键字“me”具有0个匹配,“wall”具有0个匹配,“like”0,“king”2和“apple”2。因此总匹配将是2 +2 = 4.
#2的一个问题是如何忽略包含搜索关键字的单词,例如“kingdom”包含“king”但是是一个不同的单词。
更新
根据有用的答案,我使用了全文搜索。
$keywords='bb';
$data['recommendation']=$this->db->query
("SELECT *, MATCH(keywords, phrase) AGAINST ('$keywords') as score
FROM game
WHERE MATCH(keywords, phrase) AGAINST ('$keywords')
ORDER BY score
LIMIT 3");
var_dump($data['recommendation']);
die;
由于某种原因,var_dump返回一个没有找到行的空结果。但是我在表格的至少2行中确实有“bb”这个短语,如下所示。
id | keywords | phrase
1 | bb king | I was eating an apple when bb the king hit me
2 | bb | you fancy this brush?
答案 0 :(得分:2)
正如Barmar所说,你可以使用全文功能:
SELECT id, customer_id, phrase
FROM table
WHERE MATCH(phrase) AGAINST ('me wall like king apple');
如果还需要搜索其他列,请将其添加到MATCH
:
SELECT id, customer_id, phrase
FROM table
WHERE MATCH(phrase,keywords) AGAINST ('me wall like king apple');
编辑:
对于第3点,您可以使用相同的功能:
SELECT id, customer_id, phrase, MATCH(phrase,keywords) AGAINST ('me wall like king apple') as score
FROM table
WHERE MATCH(phrase,keywords) AGAINST ('me wall like king apple')
ORDER BY score
LIMIT 3;
此查询将返回三个最佳匹配
了解更多信息take a look to the manual
更新:
根据手册:
全文搜索中会忽略某些字词:
任何太短的单词都会被忽略。通过全文搜索找到的默认最小单词长度为四个字符。
会忽略禁用词列表中的字词。禁用词是诸如“the”或“some”之类的词,它是如此常见以至于它被认为具有零语义值。有一个内置的禁用词列表,但它可以被用户定义的列表覆盖。
您使用简短的字词进行搜索,这就是您没有得到任何结果的原因。
更新09-09-14:
如果修改影响索引编制的全文变量(
ft_min_word_len
,ft_max_word_len
或ft_stopword_file
),或者更改了阻截文件本身,则必须重建{{1进行更改并重新启动服务器后的索引。要在这种情况下重建索引,只需执行FULLTEXT
修复操作即可:的MySQL> REPAIR TABLE tbl_name QUICK;
因此,执行QUICK
后,您必须执行ALTER TABLE table ADD FULLTEXT(phrase, keywords);
但仅执行一次
答案 1 :(得分:0)
$keywords=explode(' ', $keywords_raw);
if(count($keywords)>1)
{
$stmt.="(";
$i=0;
foreach($arr_s1 as $kv)
{
if($i>0)
{
$stmt.=" AND ";
}
$stmt.=" phrase like '%".$kv."%'";
$i++;
}
$stmt.=")";
}
希望它对你有用。