忽略查询中的mysql全文停用词
Posted
技术标签:
【中文标题】忽略查询中的mysql全文停用词【英文标题】:ignoring mysql fulltext stopwords in query 【发布时间】:2012-09-22 15:15:00 【问题描述】:我正在构建一个使用全文搜索的网站搜索。搜索本身效果很好,那不是我的问题。我将用户提供的关键字(匹配...反对...)与 AND 串在一起,以便多个词进一步缩小结果。现在,我知道某些停用词没有被索引,这对我来说很好,我真的不想将它们用作选择标准。但是,如果(由用户)在关键字集中提供了一个停用词,它会杀死所有结果(如预期的那样),即使该词实际上位于某个文本块中。
我的问题:有没有办法在查询时检查某个单词是否是停用词?我首选的解决方案是从搜索条件中排除相关的单词(我不在乎用户是否可以通过单词'neither'来缩小结果,我只是不希望 mysql 返回一个空的结果集,因为用户提供它,即使结果中都不存在)。或者,我是否只需要清空停用词列表?非常感谢您的帮助。
编辑---- 我很抱歉,但实际上没有代码 sn-ps 可以为这个提供。该代码工作正常,实际上完全符合预期。这更像是我正在处理的一个逻辑问题。但作为一个例子,在解释的方式上:
假设有三个记录,其中包括单词(但不限于)
1:苹果、橙子、芒果、香蕉 2:葡萄、橙子、菠萝、芒果 3:土豆、芒果、甜瓜、凯拉骑士
如果用户输入的搜索词是芒果,则所有结果都正确返回。如果单词是橙色 AND 芒果,则返回结果 1 和 2(正确)。现在,假设香蕉是一个停用词(它不是……但我们假设它是),如果搜索的是橙色、芒果和香蕉,则不会返回任何结果(因为香蕉不在全文索引中)。
我正在寻找的是是否有其他人遇到过这个问题,并且有办法解决这个问题。一种:
if 'banana' NOT STOP WORD match 'banana' against `words`. (OBVIOUSLY not real code).
或者...我是否只需要删除停用词列表...
【问题讨论】:
你尝试了什么?你能给我们举个例子吗? 似乎没有一个答案能真正得到你想要的。您总是可以编写应用程序代码来手动过滤掉查询中的任何停用词(以及太短的词)。这很可能是我们要做的。 2017 和同样的问题在这里.. 似乎 mysql 全文搜索的设计真的很差,缺乏基本功能.. 【参考方案1】:您可以通过比较所有停用词来验证关键字。这是stopwords的列表 我找到了一种从全文中禁用停用词的解决方案。 你只需要找到 .cnf 文件并添加这个,
ft_stopword_file = ""
重启mysql引擎并重建索引;
希望这项工作
【讨论】:
我在想这可能是我需要走的路线。我只是真的希望其他人有一个更聪明的解决方案。感谢您的意见。【参考方案2】:如何在 MySQL 中禁用全文停用词:
在 my.ini 文本文件 (MySQL) 中:
ft_stopword_file = "" or link an empty file "empty_stopwords.txt"
ft_min_word_len = 2
// 设置您的最小长度,但请注意较短的单词 (3,2) 会显着增加查询时间,尤其是在全文索引列字段很大的情况下。
保存文件,重启服务器。
下一步应该是使用此查询修复索引:
REPAIR TABLE tbl_name QUICK.
但是,如果您的表使用 InnoDB 存储引擎,这将不起作用。您必须将其更改为 MyISAM :
ALTER TABLE t1 ENGINE = MyISAM;
所以,再一次:
1. Edit my.ini file and save
2. Restart your server (this cannot be done dynamically)
3. Change the table engine (if needed) ALTER TABLE tbl_name ENGINE = MyISAM;
4. Perform repair REPAIR TABLE tbl_name QUICK.
请注意,InnoDB 和 MyISAM 存在速度差异。一个读得更快,另一个写得更快(在互联网上阅读更多相关内容)
【讨论】:
需要注意的是,从 MySQL 5.6 开始的 InnoDB 有全文索引【参考方案3】:使用此步骤在 mysql 中禁用全文搜索的停用词
1:在mysql中打开my.ini文件
2:放在my.ini中[mysqld]行之后的两行以下(在文件中搜索[mysqld])
ft_min_word_len=1
ft_stopword_file=""
3:重启你的服务器
4:使用以下命令修复您的表
> repair table tablename;
5:现在您的搜索正在工作......
【讨论】:
【参考方案4】:尝试使用 MATCH...AGAINST...IN BOOLEAN MODE 像这个: WHERE MATCH(作者,标题) AGAINST('"origin of"' IN BOOLEAN MODE);
【讨论】:
停用词不在全文索引中,所以即使你使用布尔模式,它也不会返回任何内容【参考方案5】:设置
ft_stopword_file = ""
对我不起作用,我使用的是 INNODB 表和 MySQL 5.6(优化关联表后,停用词仍未在全文索引中编制索引)
此解决方案有效(即使您不是超级用户):
CREATE TABLE mydb.stopwordslist(value VARCHAR(20)) ENGINE = INNODB;
INSERT INTO mydb.stopwordslist(value) VALUES ('skipthisword');
适用于所有用户,但您仍需要超级用户权限:
SET GLOBAL innodb_ft_server_stopword_table = 'mydb/stopwordslist';
仅针对用户(假设是重新创建索引和更新列的用户)
SET SESSION innodb_ft_user_stopword_table = 'mydb/stopwordslist';
因为它是一个会话变量,所以当你的会话关闭时它不会持续,所以请确保你在每次会话时设置它,或者在优化或插入具有全文索引的表之前,或者当你更新由全文索引索引的列时
【讨论】:
【参考方案6】:对于 INNODB 情况,可以在创建索引时禁用 stop_words。
SET @@SESSION.innodb_ft_enable_stopword = 'OFF';
create table foo
....
fulltext (search_col)
这将导致在禁用停用词的情况下创建全文索引。您可以使用以下查询进行验证。
SET GLOBAL innodb_ft_aux_table = 'schema/foo';
select * from information_schema.innodb_ft_config;
您的结果将如下所示:
注意 use_stopword 设置为 0。
在此 mysql documentation page. 上搜索 use_stopwords
和结帐innodb_ft_enable_stopword
here
【讨论】:
以上是关于忽略查询中的mysql全文停用词的主要内容,如果未能解决你的问题,请参考以下文章