mariadb/mysql中全文搜索的字符串转义方法

uemypmqf  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(485)

在mariadb中,某些字符(运算符)会影响全文搜索的行为。他们是 +-<>()~*" 文档中描述了它们的功能。
我希望能够搜索包含这些运算符之一的单词,我希望mariadb将其作为普通字符而不是运算符来处理。我该怎么做?
例子:
让我们用全文索引创建表:

CREATE TABLE users (username TEXT, FULLTEXT(username)) ENGINE=InnoDB;

INSERT INTO users(username) VALUES ('joseph'), ('jose'), ('jose*');

现在我要搜索包含 jose* :

SELECT * FROM users WHERE MATCH(username) AGAINST('jose*' IN BOOLEAN MODE);
+----------+
| username |
+----------+
| joseph   |
| jose     |
| jose*    |
+----------+

但我只想和你划船 jose* . 同样的结果是当我试图以我期望的方式逃逸这个字符串时。

SELECT * FROM users WHERE MATCH(username) AGAINST('jose\*' IN BOOLEAN MODE);
+----------+
| username |
+----------+
| joseph   |
| jose     |
| jose*    |
+----------+

SELECT * FROM users WHERE MATCH(username) AGAINST('jose\\*' IN BOOLEAN MODE);
+----------+
| username |
+----------+
| joseph   |
| jose     |
| jose*    |
+----------+

在mariadb/mysql中,对全文搜索的字符串进行转义的正确方法是什么?

mcvgt66p

mcvgt66p1#

全文搜索是一种有效搜索出现在(全文)任何地方的单词(或单词开头)的工具。如果您的数据不包含分隔的“单词”(以您想要定义它们的任何方式),则全文索引不是您任务的合适工具(因为它将完全无用)。默认情况下, * 是一个单词分隔符就像空格一样(例如。 '*def' ,以及 ' def' ,是两个单词,在全文索引中有两个单独的条目,其中没有一个包含 * ). 您可以指定要作为分隔符的内容,但mysql不支持通过在搜索表达式中转义来动态指定分隔符;您需要在创建索引时执行此操作,以便索引实际上包含 jose* ,而不仅仅是 jose .
如果没有单词(或一组非常有限的分隔符),可以使用。 username = 'jose* , username like 'jose*' 或类似的;或者,您可以使用正则表达式,它速度很慢,但是对于复杂的需求(例如,如果全文不适合您的情况),如果全文索引不是usabel(和/或您无法更改配置以使其适合您的需求),它是一种回退工具。
要更改mysql将哪些字符视为分隔符,可以更改字符Map,请参阅为全文索引添加排序规则:
将新排序规则添加到 index.xml 将排序规则添加到字符文件(例如。 latin1.xml ),并编辑 ctype 将特定字符定义为(非)分隔符;仅适用于 * ,改为“48 10 10 10 10 10 10 10 10 10 01 10 10 10 10 10 10 10 10 10”);对所有要搜索的字符都要这样做(但是,请记住,如果没有至少一个剩余的分隔符,则全文搜索是无用的)。
重新启动后,对列使用此排序规则(例如。 ... (username TEXT collate 'latin1_fulltext_ci', ... )然后重新创建全文索引,mysql将把这些字符包含到索引中。
请记住,您需要在每个要使用此行为的服务器上执行此操作
现在,以下三个搜索应返回预期结果:

... MATCH(username) AGAINST('"jose*"' IN BOOLEAN MODE);

... MATCH(username) AGAINST('jose*');

... MATCH(username) AGAINST('"jose*"');
``` `"..."` 将查找完全匹配的词(例如单词组合);它的工作原理类似于转义,但并不完全相同,因为它只适用于非分隔符字符。

... MATCH(username) AGAINST('jose*' IN BOOLEAN MODE);

将不适用于innodb(它将被视为通配符),但将适用于myisam(它们之间的一些细微差别之一)。
如果您真的想使用布尔模式,但需要一个通配符而不是 `*` ,可以使用 `ft_boolean_syntax` ,尽管由于innodb中的一个bug,这也只适用于myisam。它也是一个全局设置,因此会改变其他表(和数据库)中所有其他全文搜索的行为。您可能需要指定使用此模式要实现的目标,以查看是否有方法使全文搜索能够满足这些要求,但最终,您可能不得不返回使用 `like` .

相关问题