MySQL中的全文搜索:好和坏,美和丑?
Lukas Vileikis 【hudson 译】
2020年11月13日

有时在MySQL 中搜索时您可能希望对基于字符的数据运行全文搜索查询。今天我们将讨论这些搜索方法的优缺点。
MySQL中的全文搜索是什么?
全文搜索是一种使您能够搜索可能与搜索条件不完全匹配的记录的技术。MySQL中的全文搜索在使用某些索引时执行,这些索引具有许多独特的细微差别,包括以下内容:
- 为了将索引视为全文索引,索引必须是FULLTEXT类型。
- FULLTEXT索引只能用于运行InnoDB或MyISAM存储引擎的表。
- 只能为CHAR、VARCHAR或TEXT列创建FULLTEXT索引。
- FULLTEXT索引仅在使用MATCH() AGAINST()子句时使用。
- 全文搜索有三种模式:自然语言模式、布尔模式和查询扩展模式。
FULLTEXT索引是一种特殊类型的索引,它在文本中查找关键字,而不是将值与索引中的值进行比较。尽管FULLTEXT搜索不同于其他类型的匹配,但请注意,您可以在同一列上同时使用BTREE索引和FULLTECT索引–它们不会冲突,因为它们适用于不同的目的。
全文搜索类型
在[MySQL]中运行全文搜索时,请记住有三种搜索类型可供选择:
- 自然语言搜索类型–这种搜索模式将搜索字符串解释为文字短语。如果未指定修饰符或指定了IN NATURAL LANGUAGE MODE修饰符,则默认启用;
- 查询扩展搜索类型–这样的搜索模式会执行两次搜索。第二次搜索时,结果集包含第一次搜索中的一些最相关的文档。使用WITH QUERY EXPANSION修饰符启用;
- 布尔搜索类型–这样的搜索模式可以搜索复杂的查询,这些查询可以包括布尔运算符,例如小于(“<”)和大于(“>”)运算符、子表达式(“(”和“)”)、加号(+)、减号(-)、双引号(“”)、,降低值对结果的贡献的操作符(~)和通配符(*)&通配符允许使用模糊匹配进行搜索(例如,“demo”也会匹配“demonstration”)。使用IN BOOLEAN MODE修饰符启用。
使用自然语言搜索模式进行全文搜索
如上所述,自然语言搜索模式默认启用,或者在指定了IN natural language mode修饰符时启用。此模式对给定的文本集合(一列或多列)执行自然语言搜索。MySQL中全文搜索的基本查询格式应类似于以下内容:
SELECT * FROM table WHERE MATCH(column) AGAINST(“string” IN NATURAL LANGUAGE MODE);
当MATCH()与WHERE子句一起使用时,行首先按最高相关性自动排序。要搜索精确的字符串,请用双引号将其括起来。
使用查询扩展模式进行全文搜索
全文搜索也支持查询扩展模式。当用户依赖隐含知识时,经常使用这种搜索模式——例如,用户可能会搜索“DBMS”,希望在搜索结果中同时看到“MongoDB”和“MySQL”。使用这种搜索模式时,用户可能会依赖一些隐含知识,原因非常简单——使用查询扩展模式的全文搜索通过执行两次搜索来工作:第二个搜索短语是第一个搜索短语,与第一个搜索中的几个最相关的条目串联在一起。这意味着,例如,如果在第一次搜索中,其中一行包含单词“DBMS”和单词“MySQL”,那么第二次搜索将查找包含单词“MySQL”的条目,即使它们不包含“DBMS“。使用查询扩展模式的查询格式如下:
SELECT * FROM table WHERE MATCH(column) AGAINST(“string” WITH QUERY EXPANSION);
使用布尔模式进行全文搜索
布尔模式可能是MySQL全文搜索提供的最有趣的功能之一。这种模式有许多独特的警告,因为它允许您使用布尔运算符扩展搜索功能。当使用布尔模式时,某些字符在单词的开头或结尾可能有特殊含义。例如:
- “+”是指AND;
- “-”表示NOT;
- “(” 和 “)” 运算符允许创建子表达式;
- “<” 和 “>”运算符将搜索值的排名更改为更低或更高;
- “~” 会降低该值对搜索结果的贡献;
- 双引号(“”)只匹配文字值;
- “*”是通配符运算符(请参阅上面的解释)。
这些运算符允许您扩展搜索的功能:例如,如果要检索包含单词“Demo”而不是“Demo2”的所有行,可以使用如下查询:
SELECT * FROM table WHERE MATCH(column) AGAINST (“+Demo -Demo2” IN BOOLEAN MODE);
您还可以使用双引号和单引号,如下所示:
SELECT * FROM table WHERE MATCH(column) AGAINST(‘“search string”’ IN BOOLEAN MODE);
全文搜索陷阱
在 MySQL 中使用全文搜索之前,请记住,搜索确实有一些“陷阱”:
- InnoDB和MyISAM存储引擎都有自己的停用词列表。在这里 可以找到InnoDB停用词列表,在这里 可以找到MyISAM停用词列表
- 要为InnoDB定义自己的停用词列表,请定义一个与INNODB_FT_DEFAULT_STOPWORD表结构相同的表,在其中插入停用词,然后以db_name/table_name的形式设置innodb_ft_server_stopword_table选项的值。
- 要为MyISAM定义自己的停用词列表,请将ft_stopword_file变量设置为包含停止字列表的文件的路径名。在文件中,可以用除“_”和“'”之外的任何非字母数字字符分隔非索引字。默认非索引字文件位于storage/myisam/ft_static。可以通过将变量设置为空字符串来禁用停用词。
- 分区表不支持全文搜索。
- FULLTEXT索引中的所有列必须使用相同的字符集和排序规则。
- 全文搜索操作不会将%字符串视为通配符。
还有一个问题:您可能还需要记住,内置FULLTEXT解析器通过查看某些字符(包括空格(“”)、逗号(“,”)和句点(“.”))来确定单词的开头和结尾,这意味着如果搜索字符串包含一个或多个这些字符,搜索结果可能不准确。例如,如果您的数据库包含5行字符串“test.demo”,搜索查询“test.devo”可能会返回更多(10、15等)结果,包括“demo”、“string.demo_example”等,因为它将搜索“demo“而不是“test.emo”,所以您可能会遇到许多不相关的匹配项。如果您愿意用C或C++编写自己的插件,MySQL确实为这个问题提供了一个解决方案(参见MySQL文档) ,但在那之前,你不能做太多。 MySQL全文搜索局限的完整列表可以在MySQL的文档页面 中查看。
小结
MySQL全文搜索功能提供了一种在运行MySQL的应用程序中实现各种搜索技术(自然语言搜索、查询扩展搜索和布尔搜索)的简单方法。每种搜索技术都有自己的警告,并且每种技术都可能适用于不同的目的——在决定是否使用全文搜索时,请记住,这种类型的搜索有许多独特的微妙之处,应了解MySQL使用全文搜索的优缺点,并明智地选择。