在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中,对全文搜索的字符串进行转义的正确方法是什么?
1条答案
按热度按时间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);