首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按排序规则排序

按排序规则排序
EN

Stack Overflow用户
提问于 2012-09-19 23:42:03
回答 5查看 8.2K关注 0票数 8

有收藏的:

代码语言:javascript
复制
{"name": "a"},
{"name": "B"},    
{"name": "b"},    
{"name": "c"},    
{"name": "á"},    
{"name": "A"}

例如。如何在西班牙语中排序它不区分大小写?

我试过了:

代码语言:javascript
复制
var abc = [{"name": "a"}, {"name": "B"}, {"name": "b"}, {"name": "c"}, {"name": "á"}, {"name": "A"}];
for (i in abc) db.abc.save(abc[i]);

db.abc.find({},{"_id":0}).sort({"name":1});

输出为:

代码语言:javascript
复制
[
    { "name" : "A" },
    { "name" : "B" },
    { "name" : "a" },
    { "name" : "b" },
    { "name" : "c" },
    { "name" : "á" },
]

期望的结果:

代码语言:javascript
复制
[
    { "name" : "a" },
    { "name" : "á" },
    { "name" : "A" },
    { "name" : "b" },
    { "name" : "B" },
    { "name" : "c" }
]
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-06-04 13:55:46

我知道这是一个老帖子,但我认为不管怎样,回答都会很有用。

您肯定不想在您的应用程序中进行排序,因为这意味着您必须将集合中的所有文档放入内存中,以便对它们进行排序并返回您想要的窗口。如果你的收集量很大,那么这是非常低效的。数据库应该对窗口进行排序并将其返回给您。

但是,您可能会说,MongoDB不支持区域敏感排序。你如何解决这个问题?神奇的是“排序键”的概念。

基本上,假设您有从"a“到"z”的常规英语/拉丁字母表。你要做的就是创建一个从"a“到"01”,从"b“到"02",再到"z”到"26“的排序关键字映射。也就是说,按照该语言的排序顺序将每个字母映射到一个数字,然后将该数字编码为字符串。然后,将要排序的字符串映射到此类型的排序关键字。例如,"abc“将变为"010203”。然后,使用属性的排序关键字将属性添加到文档中,并在属性的名称后面附加区域设置的名称:

代码语言:javascript
复制
{
    name: "abc",
    name_en: "010203"
}

现在,您只需在属性"name_en“上建立索引,就可以在"en”语言中进行排序,并对选择器和范围使用普通的基于英语的MongoDB排序,而不是使用"name“属性。

现在,假设你有另一种疯狂的语言"xx“,其中字母表的顺序是"acb”而不是"abc“。(是的,有些语言会以这种方式扰乱拉丁字母的顺序!)排序关键字如下所示:

代码语言:javascript
复制
{
    name: "abc",
    name_en: "010203",
    name_xx: "010302"
}

现在,您所要做的就是在name_en和name_xx上创建索引,并使用常规的MongoDB排序,以便在这些区域设置上正确排序。基本上,额外的属性是在不同地区排序的代理。

那么,您会问,这些映射是从哪里获得的?毕竟,你不是全球化专家,对吧?

如果您使用的是Java、C或C++,有现成的类可以为您完成此映射。在Java语言中,使用标准的排列器类,或者使用icu4j排列器类。如果使用的是C/C++,请使用ICU排序器函数/类的C/C++版本。对于其他语言,除非你能找到一个已经可以做到这一点的库,否则你就有点倒霉了。

这里有一些链接可以帮助你找到它们:

标准的Java库排序器: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变体不敏感,或以上的任意组合。唯一的问题是,现在您有许多与每个可排序属性并行的属性,当您更新基本的"name“属性时,您必须使它们保持同步。这是一个痛苦的你知道什么,但仍然,它比做排序在您的应用程序或业务逻辑层。

同时也要注意游标的范围。例如,在英语中,我们只是忽略字符上的重音。因此,“?”的排序方式与"O“相同,它将出现在"M”到"Z“的范围内。但是,在瑞典语中,重音字符排在"Z“之后。因此,如果你做一个范围"M“- "Z",你将包括一堆以"Ö”开头的记录,这些记录应该是英语的,而不是瑞典语的。

如果对文档的文本属性进行拆分,这也会影响到分片。要注意哪些范围属于哪个分片。最好是在不区分区域设置的东西上进行分片,比如散列。

票数 10
EN

Stack Overflow用户

发布于 2016-11-04 00:15:13

尽管这里的其他答案对于MongoDB版本3.2.x和以前的版本是正确的,但是从3.4.0开始,您可以“为支持排序规则的集合或视图、索引或特定操作指定排序规则”。

Full documentation for the feature is here

票数 11
EN

Stack Overflow用户

发布于 2012-09-19 23:52:49

目前,MongoDB还没有实现排序。

实现Unicode collation standard是解决这个问题的最好方法。

但这会使排序变慢,并使索引变得更大。所以现在,最好在你的应用程序中进行排序。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12498156

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档