如何使用 mongoDB 对 Thai 字段进行排序,如下面的 SQL 命令?
SELECT * FROM employee ORDER BY CONVERT(name USING tis620)
如何使用 mongoDB 对 Thai 字段进行排序,如下面的 SQL 命令?
SELECT * FROM employee ORDER BY CONVERT(name USING tis620)
目前,MongoDB 无法按“Unicode 代码点”以外的任何内容进行排序。我们的问题跟踪器中有一个问题:https ://jira.mongodb.org/browse/SERVER-1920 ,它跟踪 MongoDB 中包含基于区域设置且不区分大小写的排序。
其实有办法的!(虽然这是一个黑客。)
我知道这是一个较旧的线程,但我认为无论如何回答都会很有用。
您绝对不想在您的应用程序中进行排序,因为这意味着您必须将集合中的所有文档放入内存中才能对它们进行排序并返回您想要的窗口。如果您的收藏量很大,那么这是非常低效的。数据库应该进行排序并将窗口返回给您。
但是,您说,MongoDB 不支持对区域设置敏感的排序。你如何解决问题?神奇的是“排序键”的概念。
基本上,假设您有从“a”到“z”的常规英语/拉丁字母。您要做的是创建一个从“a”到“01”以及从“b”到“02”等到“z”到“26”的排序键映射。也就是说,将每个字母按该语言的排序顺序映射到一个数字,然后将该数字编码为字符串。然后,将要排序的字符串映射到这种类型的排序键。例如,“abc”将变为“010203”。然后使用属性的排序键将属性添加到文档中,并将属性名称附加到区域设置的名称中:
{
name: "abc",
name_en: "010203"
}
现在,您可以通过对属性“name_en”进行索引来以语言“en”进行排序,并对选择器和范围使用简单的、基于英语的 MongoDB 排序而不是“name”属性。
现在,假设您有另一种疯狂的语言“xx”,其中字母的顺序是“acb”而不是“abc”。(是的,有些语言会以这种方式混淆拉丁字母的顺序!)排序键是这样的:
{
name: "abc",
name_en: "010203",
name_xx: "010302"
}
现在,您所要做的就是在 name_en 和 name_xx 上创建索引并使用常规 MongoDB 排序以便在这些语言环境上正确排序。基本上,额外的属性是在不同语言环境中排序的代理。
那么你从哪里得到这些映射,你问?毕竟,你不是全球化专家,对吧?
好吧,如果您使用的是 Java、C 或 C++,则可以使用现成的类为您执行此映射。在 Java 中,使用标准的 Collator 类,或者使用 icu4j Collator 类。如果您使用 C/C++,请使用 ICU Collator 函数/类的 C/C++ 版本。对于其他语言,除非你能找到一个已经这样做的库,否则你有点不走运。
我知道 Java 和 ICU 都支持泰语语言环境,并且可以用泰语进行适当的排序。只需确保所有字符串都以 UTF-8 正确编码。
这里有一些链接可以帮助您找到它们:
标准 Java 库 Collator:http://docs.oracle.com/javase/7/docs/api/java/text/Collator.html#getCollationKey(java.lang.String)
C++ 整理器类:http ://icu-project.org/apiref/icu4c/classicu_1_1Collator.html#ae0bc68d37c4a88d1cb731adaa5a85e95
您还可以创建不同的排序键,允许您对每个区域设置不区分大小写(是的,大小写映射是区域设置敏感的!)和不区分重音,不区分 Unicode 变体,或以上任意组合。唯一的问题是,现在您有许多与每个可排序属性平行的属性,当您更新基本“名称”属性时,您必须使它们保持同步。这对于你知道什么是一种痛苦,但它仍然比在你的应用程序或业务逻辑层中进行排序要好。
还要小心带有范围的游标。例如,在英语中,我们只是忽略了字符上的重音。因此,“Ö”的排序方式与“O”相同,它将出现在“M”到“Z”的范围内。但是,在瑞典语中,重音字符排在“Z”之后。因此,如果您使用“M”-“Z”范围,您将包含一堆以“Ö”开头的记录,这些记录应该在英语中出现,而不是在瑞典语中。
如果您在文档的文本属性上进行拆分,这也会对分片产生影响。请注意哪些范围进入哪个分片。最好对不区分区域设置的事物(例如哈希)进行分片。