Mongo按嵌套数组中的多个字段排序

时间:2013-07-09 17:52:50

标签: arrays mongodb sorting multikey

我有一个mongo集合,其中包含像

这样的文档
{
_id : 1abc,
'data' :'blah',
'createdDate' : ISODate("2013-05-26T01:34:10Z"),
'a': [
    {
        _id : a1adas,
        'createdDate' : ISODate("2013-05-26T01:35:10Z"),
        'b':[
                {
                    _id : aadaasd
                    'createdDate' : ISODate("2013-05-26T01:37:10Z"),
                }
            ]
    }
]

}

我需要按相反的时间顺序对文档进行排序,以便在任何级别上具有最新createdDate的文档是第一个。

到目前为止,我有这个查询,我不确定是否按预期工作。

db.collection.find({'data':'blah'}).sort({'createdDate':-1, 'a.createdDate': -1, 'a.b.createdDate': -1 }).explain();

我想知道是否有更有效的方法来执行这样的排序。

1 个答案:

答案 0 :(得分:2)

您的查询没有做您想做的事情。多个字段上的MongoDB排序将依次处理每个字段,而不是所有三个字段。例如,我已经将一些测试文档插入到集合中,并且我运行了类似的类型:

> db.numbers.find().sort( { a : -1, b : -1, c : -1 })
{ doc : "doc1", "a" : 13, "b" : 5, "c" : 7 }
{ doc : "doc2", "a" : 12, "b" : 20, "c" : 91 }
{ doc: "doc3", "a" : 2, "b" : 50, "c" : 700 }

“doc3”具有最低的a值,因此最后返回。但是,它也具有该类别中任何字段的最高值,因此理论上我们希望它是返回的第一个东西。我们可以使用MongoDB的aggregation framework

来做到这一点
db.numbers.aggregate(
{ $project : { 
    _id : 1, 
    a : 1, 
    maxNum : { $cond: [{ $gte : [ "$b", "$c" ]}, "$b" , "$c" ]} // max of b, c
    }},
{ $project : { 
   _id : 1, 
   maxNum : { $cond: [{ $gte : [ "$a", "$maxNum" ]}, "$a" , "$maxNum" ]} // max of a, b, c 
   }}, 
{ $sort : { maxNum : -1 } } 
)

此聚合查询会将您的数据转换为可以正确执行排序的表单。但是,要看它的表现并不容易。目前没有.explain()函数用于聚合查询。