首页 > 解决方案 > 布尔模式下的 MySQL FullText:搜索包含“+”作为字符串一部分的关键字

问题描述

我已经看过十几个“类似”的问题,但没有运气。我知道+在 BOOLEAN 模式下附加到 FULLTEXT 中的关键字具有特殊含义,但是,如果我们的关键字实际上包含+符号作为文本/字符串的后缀部分怎么办。我们如何仍然使用 FULL-TEXT 搜索并获得正确的结果?

数据库结构

CREATE TABLE `ft_test` (
  `i_id` int(11) NOT NULL,
  `i_desc` mediumtext NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

ALTER TABLE `ft_test`
  ADD PRIMARY KEY (`i_id`) USING BTREE;
ALTER TABLE `ft_test` ADD FULLTEXT KEY `i_desc` (`i_desc`);

ALTER TABLE `ft_test`
  MODIFY `i_id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;

数据库数据

SELECT * FROM ft_test;
+------+-----------+
| i_id | i_desc    |
+------+-----------+
|    1 | test      |
|    2 | test+     |
|    3 | test++    |
|    4 | test +    |
|    5 | test plus |
+------+-----------+

测试#1:喜欢查询

SELECT * FROM ft_test WHERE i_desc LIKE 'test+%';
+------+--------+
| i_id | i_desc |
+------+--------+
|    2 | test+  |
|    3 | test++ |
+------+--------+

测试#2:全文查询

SELECT *, MATCH(`i_desc`) AGAINST ('"test+"' IN BOOLEAN MODE) AS RELEVANCE
    -> FROM `ft_test`
    -> WHERE MATCH(`i_desc`) AGAINST ('"test+"' IN BOOLEAN MODE)
    -> ORDER BY RELEVANCE;

+------+-----------+-----------+
| i_id | i_desc    | RELEVANCE |
+------+-----------+-----------+
|    1 | test      |         1 |
|    2 | test+     |         1 |
|    3 | test++    |         1 |
|    4 | test +    |         1 |
|    5 | test plus |         1 |
+------+-----------+-----------+

如您所见,在这种情况下, LIKE查询实际上返回和排序结果更好。我也尝试过使用引号进行完全匹配,结果相同。添加像“test\+”这样的“特殊”字符也无济于事。虽然,FT 结果并非毫无用处,但它们并不完美,因为排序不是我所期望的。

问题

实际上是否有可能实现这一点并返回与使用FULLTEXT模式的 LIKE 相同的结果?如果是,如何?

谢谢!

标签: mysqlsqlfull-text-searchmariadb

解决方案


如果您将列定义为使用将字符视为普通字母而不是标点符号的排序规则,则只能索引标点符号字符。

有一个手册页显示了执行此操作的步骤:https ://dev.mysql.com/doc/refman/8.0/en/full-text-adding-collat​​ion.html

但是由于您说您的脚本是硬编码的,我想您无权重新定义您正在搜索的列的排序规则,或者在安装自定义排序规则定义后重新启动 MySQL 服务器。

一种解决方法是搜索没有标点符号的单词,然后在找到匹配的单词后添加要应用的条件。

SELECT *, MATCH(`i_desc`) AGAINST ('"test"' IN BOOLEAN MODE) AS RELEVANCE
FROM `ft_test`
WHERE MATCH(`i_desc`) AGAINST ('"test"' IN BOOLEAN MODE)
 AND i_desc LIKE 'test+%';
ORDER BY RELEVANCE;

它将使用全文索引来查找与该单词匹配的行,然后另一个条件术语将针对+包含包含字符串的那些行(希望很小)进行过滤。

但同样,如果您无权更改 SQL 查询,那么这是没有实际意义的。


推荐阅读