如何使重音不敏感的`MATCH() AGAINST()`句子?
How to make an accent insensitive `MATCH() AGAINST()` sentence?
我有一个名为 products
的 table,它有一个名为 name
的 varchar
列,编码为 latin1_swedish_ci
。
我正在尝试进行搜索查询,以便使用 MATCH() AGAINST()
句子 name
过滤产品,如下所示:
SELECT *
FROM products
WHERE MATCH(name) AGAINST('*search_string*' IN BOOLEAN MODE)
它在没有重音符号的情况下工作得很好,但是,如果我有一个名为 Colágeno
的产品并且搜索输入是 Colageno
,查询将无法捕获该产品。
所以我尝试了 this SO answer 中显示的内容,但没有成功。
SELECT *
FROM products
WHERE MATCH(CONVERT(BINARY(name) USING utf8)) AGAINST('*Colageno*' IN BOOLEAN MODE)
我收到错误:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CONVERT(BINARY(name) USING utf8)) AGAINST('*Colageno*' IN BOOLEAN MODE)' at line 3
我只想捕捉像á, é, í, ó, ú
.
这样的特殊字符
提前致谢!
正如答案的作者所指出的,您可以使用 CONVERT(BINARY(name) USING utf8)
而不是 CONVERT(BINARY(name) USING utf8)
。
MySQL 在将 varchar 值转换为全文时已经将它们转换为二进制值。
您在创建索引时需要考虑到这一点,否则您最终将搜索二进制数据而不是 varchar 数据。
另一种解决方案是为您的 varchar 列使用某种排序规则,比方说 latin1_general_ci
。这样,搜索将始终将数据转换为二进制数据(如果 varchar 列还不是二进制数据)并在索引中以字节形式查找它。
您可以阅读更多相关信息 here。
已解决!
经过评论的讨论,我发现错误不在MATCH() AGAINST()
语句中,因为它默认不区分变音符号。
所以问题与变音符号如何存储在 MySQL 中有关,在我的例子中,它们是这样存储的 COLÁGENO
-> COLÃ<0x81>GENO
。因此,有必要找出如何在不破坏 table.
的情况下正确保存波浪号
编码
我尝试通过在 phpmyadmin 中执行以下指令来更改编码:
ALTER TABLE products CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
但是,性能没有变化。
然后我尝试通过将 DEFAULT CHARSET=latin1
更改为 DEFAULT CHARSET=utf8mb4
来更改导出的 table 文件中的编码,但结果也没有任何变化。
手动修改重音
我的另一个尝试是,一旦进行了编码更改,就可以通过波浪号 Á
对应的字符手动修改具有 Ã<0x81>
等字符的单元格。但遗憾的是,这似乎破坏了对 table 的查询(我仍然能够正常访问其他 table)。
所以我想到了 masterguru 在评论中所说的关于编码更改改变脚本连接到 table 的方式,显然当我手动修改一个字符以放置波浪号时,脚本继续访问 table。 table 使用之前的编码。
解决方案
脚本在 PHP 中,因此我必须找到该语言的解决方案。
我发现 this answer 是英文的,其中说明了如何在数据库中正确保存波浪号。为此,您必须编写...
mysqli_set_charset($connection, "utf8");
...这是在连接到数据库之后。最后,我不得不将数据库中的稀有字符更改为相应的波浪字符,以便 MATCH AGAINST
起作用,瞧!
非常感谢 masterguru、Triby 和 aeportugal 在评论中提供的帮助!
我有一个名为 products
的 table,它有一个名为 name
的 varchar
列,编码为 latin1_swedish_ci
。
我正在尝试进行搜索查询,以便使用 MATCH() AGAINST()
句子 name
过滤产品,如下所示:
SELECT *
FROM products
WHERE MATCH(name) AGAINST('*search_string*' IN BOOLEAN MODE)
它在没有重音符号的情况下工作得很好,但是,如果我有一个名为 Colágeno
的产品并且搜索输入是 Colageno
,查询将无法捕获该产品。
所以我尝试了 this SO answer 中显示的内容,但没有成功。
SELECT * FROM products WHERE MATCH(CONVERT(BINARY(name) USING utf8)) AGAINST('*Colageno*' IN BOOLEAN MODE)
我收到错误:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CONVERT(BINARY(name) USING utf8)) AGAINST('*Colageno*' IN BOOLEAN MODE)' at line 3
我只想捕捉像á, é, í, ó, ú
.
提前致谢!
正如答案的作者所指出的,您可以使用 CONVERT(BINARY(name) USING utf8)
而不是 CONVERT(BINARY(name) USING utf8)
。
MySQL 在将 varchar 值转换为全文时已经将它们转换为二进制值。
您在创建索引时需要考虑到这一点,否则您最终将搜索二进制数据而不是 varchar 数据。
另一种解决方案是为您的 varchar 列使用某种排序规则,比方说 latin1_general_ci
。这样,搜索将始终将数据转换为二进制数据(如果 varchar 列还不是二进制数据)并在索引中以字节形式查找它。
您可以阅读更多相关信息 here。
已解决!
经过评论的讨论,我发现错误不在MATCH() AGAINST()
语句中,因为它默认不区分变音符号。
所以问题与变音符号如何存储在 MySQL 中有关,在我的例子中,它们是这样存储的 COLÁGENO
-> COLÃ<0x81>GENO
。因此,有必要找出如何在不破坏 table.
编码
我尝试通过在 phpmyadmin 中执行以下指令来更改编码:
ALTER TABLE products CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
但是,性能没有变化。
然后我尝试通过将 DEFAULT CHARSET=latin1
更改为 DEFAULT CHARSET=utf8mb4
来更改导出的 table 文件中的编码,但结果也没有任何变化。
手动修改重音
我的另一个尝试是,一旦进行了编码更改,就可以通过波浪号 Á
对应的字符手动修改具有 Ã<0x81>
等字符的单元格。但遗憾的是,这似乎破坏了对 table 的查询(我仍然能够正常访问其他 table)。
所以我想到了 masterguru 在评论中所说的关于编码更改改变脚本连接到 table 的方式,显然当我手动修改一个字符以放置波浪号时,脚本继续访问 table。 table 使用之前的编码。
解决方案
脚本在 PHP 中,因此我必须找到该语言的解决方案。
我发现 this answer 是英文的,其中说明了如何在数据库中正确保存波浪号。为此,您必须编写...
mysqli_set_charset($connection, "utf8");
...这是在连接到数据库之后。最后,我不得不将数据库中的稀有字符更改为相应的波浪字符,以便 MATCH AGAINST
起作用,瞧!
非常感谢 masterguru、Triby 和 aeportugal 在评论中提供的帮助!