2010-07-09 176 views
30

我知道如何通过多个字段对MongoDB中的查询进行排序,例如db.coll.find().sort({a:1,b:-1})Mongo复杂排序?

我可以使用用户定义的函数进行排序吗?例如,假设a和b是整数,则a和b之间的差值为(a-b)

谢谢!

+1

我遇到了同样的问题。你能找到一种方法在服务器端实现这一点吗?我真的宁愿不必在客户端上这样做,或者添加额外的字段。 – 2011-03-09 19:17:52

回答

29

更新:此答案似乎已过时;似乎可以通过使用$project function of the aggregation pipeline在排序之前转换输入文档或多或少地实现自定义排序。另见@阿里的回答。

我不认为这是可能的直接; sort documentation肯定没有提及任何提供自定义比较功能的方法。

您可能最擅长在客户端进行排序,但如果您真的决定在服务器上执行此操作,则可以使用db.eval()安排在服务器上运行排序(如果您的客户端支持它)。

服务器端排序:

db.eval(function() { 
    return db.scratch.find().toArray().sort(function(doc1, doc2) { 
    return doc1.a - doc2.a 
    }) 
}); 

对战相当于客户端排序:

db.scratch.find().toArray().sort(function(doc1, doc2) { 
    return doc1.a - doc2.b 
}); 

注意,它也可以通过aggregation pipeline进行排序,并通过$orderby operator(即除.sort())但是,这些方式都不能让您提供自定义排序功能。

+2

是的。在进一步挖掘之后,我发现有一个RFE提交给方便的功能来完成这件事。我绝对不喜欢'toArray()'的外观来看我的~10m文件,但这显然是事态。 – gilesc 2010-07-09 14:56:23

+0

Hi @gilesc。请您告诉我您是如何完全使用“RFE提交”的细节?我处于同样的情况。 – LotusH 2012-05-04 03:38:33

+1

@Wasabi我认为他是指这个:https://jira.mongodb.org/browse/SERVER-153这是不可能的,但有一张票打开,他们正在考虑实施它。但它已开放多年,所以不知道它是否会发生。 – rmarscher 2012-05-09 17:03:52

11

为什么不用此操作创建字段并对其进行排序?

+3

我仍然需要单独访问a和b。所以我必须创建第三个领域。 这将适用于我的应用程序,但作为一般原则将是非常糟糕的政策。假设我有几个整数字段,将会有派生属性(a-b),(a-c),(a-d)的组合爆炸......即使只有一个这样的字段,对于大型集合来说也是浪费空间。 我upvoting,如果没有人回答接受,但必须有一个更好的方法。在SQL中,这与“SELECT * FROM coll ORDER BY(a-b)'一样简单。 – gilesc 2010-07-09 13:39:15

+1

请注意,尽管您可以在SQL中执行此操作,但效率并不高。数据库必须获取所有a和b值,计算a-b,对结果进行排序并返回相关记录。对于Mongo来说,这意味着如果你没有a和b上的索引,那么将所有文档加载到内存中。如果你创建一个新的字段,你可以在这个字段上创建一个索引,这会使这个查询真的很快。 – konrad 2013-01-06 16:03:16

+0

好主意。只要记录位置的值本地化为记录本身的数据,就可以完美分摊计算插入/更新排序的成本。 – DoctorPangloss 2013-06-01 23:14:33

15

冉到这一点,这就是我想出了:

db.collection.aggregate([ 
    { 
    $project: { 
     difference: { $subtract: ["$a", "$b"] } 
     // Add other keys in here as necessary 
    } 
    }, 
    { 
    $sort: { difference: -1 } 
    } 
])