【问题标题】:Search 5 keywords in mysql table在mysql表中搜索5个关键字
【发布时间】:2014-09-08 05:29:52
【问题描述】:

我正在尝试从用户在 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);

.... 这就是我卡住的地方。我的想法是:

  1. 搜索将针对每个关键字执行,例如“me”、“wall”、“like”等

  2. 对于每个关键字,它将在表格的每一行中搜索“关键字”和“短语”这两个列,并返回找到的匹配数。例如,搜索第一行输入的关键字将返回关键字“me”有 0 个匹配项,“wall”有 0 个匹配项,“like”有 0 个,“king”有 2 个,“apple”有 2 个。因此总匹配项为 2 +2 = 4。

  3. 最后,比较从所有行中找到的匹配总数,并选择匹配最多的前 3 行。

#2 的一个附带问题是如何忽略包含搜索关键字的单词,例如包含“king”但属于不同单词的“kingdom”。


更新:

根据有用的答案,我使用了全文搜索。

    $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?   

【问题讨论】:

  • 这是一个全文搜索的工作。在 MySQL 文档中阅读它。

标签: php mysql search full-text-search sql-like


【解决方案1】:

正如 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”之类的词,它非常常见,以至于被认为具有零语义值。有一个内置的停用词列表,但它可以被用户定义的列表覆盖。

您正在使用一个简短的单词进行搜索,这就是您没有得到任何结果的原因。

2014 年 9 月 9 日更新:

来自documentation

如果您修改影响索引的全文变量(ft_min_word_lenft_max_word_lenft_stopword_file),或者如果您更改了停用词文件本身,则必须在进行更改后重建您的 FULLTEXT 索引并重新启动服务器。在这种情况下要重建索引,只需执行QUICK 修复操作即可:

mysql> 修复表 tbl_name QUICK;

因此,在执行ALTER TABLE table ADD FULLTEXT(phrase, keywords); 之后,您必须执行REPAIR TABLE tbl_name QUICK;只能执行一次

【讨论】:

  • 谢谢!我尝试使用选项 3,但收到以下错误:找不到与列列表匹配的 FULLTEXT 索引。有什么建议吗?
  • 你需要执行这个:ALTER TABLE table ADD FULLTEXT(phrase, keywords);
  • 就这么做了。它现在可以正常工作,没有短语问题,但是在进行搜索时没有返回结果。我可以邀请您看一下问题更新吗?谢谢!
  • 谢谢。无论如何要覆盖短搜索忽略规则?原因是被搜索的关键字是标签,有时它们确实很短:“IE”、“Alt”、“F6”等。我正在阅读dev.mysql.com/doc/refman/5.0/en/fulltext-fine-tuning.html 的手册,但有点迷茫
  • 我从不调整它,但根据文档,您可以定义全文单词的长度。将此添加到 my.cnf 文件 [mysqld] ft_min_word_len=1.
【解决方案2】:
  $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.=")";                    

                 }

希望它对你有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-17
    • 2011-01-12
    • 2013-04-25
    • 2010-10-07
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 2011-09-28
    相关资源
    最近更新 更多