忽略查询中的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_stopwordhere

【讨论】:

以上是关于忽略查询中的mysql全文停用词的主要内容,如果未能解决你的问题,请参考以下文章

我可以以编程方式配置 PostgreSQL 以不消除全文搜索中的停用词吗?

SQL 2008:关闭全文搜索查询的停用词

即使停用词列表为空,如果包含停用词,全文搜索也不起作用

如何获取我的全文目录中使用的停用词列表?

只忽略 ngram_range=1 的停用词

如何使用 elasticsearch nest api 创建自定义分析器以忽略重音和 pt-br 停用词?