让我假装我的wiki中有这些页面标题(MediaWiki 1.19.4):
SOMETHIng
Sómethìng
SomêthÏng
SÒmetHínG
Run Code Online (Sandbox Code Playgroud)
如果用户搜索something我想要返回所有4个页面作为结果.
目前,我唯一能想到的就是这个查询(MySQL Percona 5.5.30-30.2):
SELECT page_title
FROM page
WHERE page_title LIKE '%something%' COLLATE utf8_general_ci
Run Code Online (Sandbox Code Playgroud)
哪个只返回SOMETHIng.
我必须走正确的道路,因为如果我搜索sóméthíngOR SÓMÉTHÍNG,我会得到SOMETHIng结果.我怎样才能修改查询,以便按预期获得其他结果?由于该page表仅包含~2K行,因此性能并不重要.
这是具有相关位的表定义:
CREATE TABLE page (
(...)
page_title VARCHAR(255) NOT NULL DEFAULT '' COLLATE latin1_bin,
(...)
UNIQUE INDEX name_title (page_namespace, page_title),
)
Run Code Online (Sandbox Code Playgroud)
不能修改表定义,因为这是MediaWiki和AFAIK的库存安装,其代码期望以这种方式定义该字段(即unicode存储为二进制数据).
我找到了完美的解决方案,无需修改或创建表格。它可能会对性能产生影响(我没有测试),但正如我在问题中所说,它是一个大约 2K 行的表,所以它应该不重要。
\n\n问题的根源在于MediaWiki 将 UTF8 编码的文本存储在 latin1 编码的表中。这对 MediaWiki 来说并不重要,因为它知道这一点,并且总是使用正确的字符集查询数据库并执行其操作,本质上使用 MySQL 作为一个哑位容器。这样做是因为显然 MySQL 中的 UTF8 支持不足以满足其需求(请参阅 MediaWiki\'s 中的注释DefaultSettings.php,变量$wgDBmysql5中的注释)。
当您希望数据库本身能够执行 UTF8 感知操作(就像我在问题中想做的那样)时,就会出现问题。你将无法做到这一点,因为据 MySQL 所知,它不存储 UTF8 编码的文本(尽管确实如此,如上一段所述)。
\n\n有一个明显的解决方案:将您要使用的列转换为 UTF8,如下所示CONVERT(col_name USING utf8)。这里的问题是 MySQL 试图提供危险的帮助:它认为col_name存储的是 latin1 编码的文本,并且它会翻译(而不是编码)每个字节翻译(而不是编码)为其 UTF8 等效项,并且您将以双重编码的 UTF8 结束,这显然是错误的。
如何避免 MySQL 变得如此友善和乐于助人?在转换为 UTF8之前先转换为 BINARY !这样,MySQL 就不会做出任何假设,并且会完全按照要求执行操作:将这串位编码为 UTF8。确切的语法是CONVERT(CAST(col_name AS BINARY) USING utf8).
所以这是我现在的最后一个查询:
\n\nSELECT CONVERT(CAST(page_title AS BINARY) USING utf8)\nFROM page\nWHERE\n CONVERT(CAST(page_title AS BINARY) USING utf8)\n LIKE \'%keyword_here%\'\n COLLATE utf8_spanish_ci\nRun Code Online (Sandbox Code Playgroud)\n\n现在如果我搜索something或s\xc3\xb4M\xc3\xabth\xc3\xaeNG任何变体,我会得到所有结果!
请注意,我使用它是utf8_spanish_ci因为我希望搜索能够区分\xc3\xb1而n不是\xc3\xa1区分a。根据您的用例使用不同的排序规则(这是完整列表)。
相关链接:
\n\n\n| 归档时间: |
|
| 查看次数: |
1201 次 |
| 最近记录: |