我正在尝试使用全文索引来搜索其中包含“,”的内容。
但是我不能,详情如下。(mysql 5.7.20, MyISAM)
如果我在搜索词中加上“,”,我找不到任何结果。
mysql> select * from tmp;
+-----------------+
| book_name |
+-----------------+
| hi,there |
+-----------------+
1 rows in set (0.00 sec)
mysql> select book_name from tmp where match(book_name) against('"hi,there"' in boolean mode);
Empty set (0.00 sec)
可以看到空集返回了。为什么? 我的设置如下:
mysql> show create table tmp;
show create table tmp;
+-------+--------------+
| Table | Create Table |
+-------+--------------+
| tmp | CREATE TABLE `tmp` (
`book_name` char(32) NOT NULL,
FULLTEXT KEY `book_name` (`book_name`) /*!50100 WITH PARSER `ngram` */
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 |
+-------+--------------+
1 row in set (0.00 sec)
mysql> show variables like '%ngram%';
show variables like '%ngram%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| ngram_token_size | 2 |
+------------------+-------+
1 row in set (0.01 sec)
mysql> show variables like '%stopword%';
show variables like '%stopword%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| ft_stopword_file | |
| innodb_ft_enable_stopword | ON |
| innodb_ft_server_stopword_table | |
| innodb_ft_user_stopword_table | |
+---------------------------------+-------+
4 rows in set (0.00 sec)
为什么?
默认全文索引考虑词,逗号不是词的一部分。来自自然语言全文搜索文档:
相关性是根据行(文档)中的单词数、行中唯一单词的数量、集合中的单词总数以及包含特定单词的行数来计算的。
[...]
内置的 FULLTEXT 解析器通过查找特定的分隔符来确定单词的开始和结束位置;例如,(空格)、、(逗号)和 。 (时期)。如果单词没有用分隔符分隔(例如中文),内置的 FULLTEXT 解析器无法确定单词的开始或结束位置。为了能够将此类语言中的单词或其他索引术语添加到使用内置 FULLTEXT 解析器的 FULLTEXT 索引,您必须对它们进行预处理,以便它们由任意定界符分隔。或者,您可以使用 ngram 解析器插件(用于中文、日语或韩语)或 MeCab 解析器插件(用于日语)创建 FULLTEXT 索引。
来自布尔全文搜索文档:
用双引号 (") 字符括起来的短语只匹配字面上包含该短语的行,因为它是键入的。全文引擎将短语拆分为单词,并在全文索引中搜索单词。非单词字符不需要完全匹配:短语搜索只需要匹配包含与短语完全相同的单词并且顺序相同。例如,“test phrase”匹配“test, phrase”。
如果您的文本和查询是,例如,“unladen,swallow”,到目前为止一切顺利:您的查询将搜索彼此相邻的词“unladen”和“swallow”,忽略逗号。你没有得到任何结果的原因是因为“hi”低于字长阈值,而“there”在 MyISAM 表中有一个stopword,使你的查询实际上是空的。来自文档:
任何太短的词都会被忽略。全文搜索找到的单词的默认最小长度对于 InnoDB 搜索索引是三个字符,对于 MyISAM 是四个字符。您可以通过在创建索引之前设置配置选项来控制截止:InnoDB 搜索索引的
配置选项,或 MyISAM 的innodb_ft_min_token_size
。ft_min_word_len
换句话说,您真正遇到问题的不是逗号,而是您要搜索的词。如果您的数据和查询是“hi there”,您会得到相同的结果(或者更确切地说,同样缺少结果)。
如果您将索引更改为 ngram 索引,您的查询将起作用,因为它在字符级别而不是单词级别起作用,并且不会区别对待逗号。它仍然使用相同的停用词列表,但它只排除包含停用词的标记;由于您的最大标记大小定义为 2,因此您不能将
there
,甚至 the
作为停用词进行处理。
这相关吗?
---- 2018-07-27 8.0.12 全面上市 & 2018-07-27 5.7.23 全面上市 -- -- InnoDB -----
ngram 全文搜索解析器允许将逗号和句点字符标记为单词,这导致布尔和自然语言模式搜索结果之间不一致。逗号和句点字符不再标记化。 (错误号 27847697)