MongoDB:按名称未知的子文档排序

时间:2014-07-18 11:52:49

标签: performance mongodb mapreduce aggregation-framework

我有一个像这样的MongoDB集合:

{
 id: "213",
 sales : {
     '2014-05-23': {
        sum: 23
     },
     '2014-05-22': {
        sum: 22    
     }
 }
},

{
 id: "299",
 sales : {
     '2014-05-23': {
        sum: 44
     },
     '2014-05-22': {
        sum: 19    
     }
 }
},

我正在寻找一个查询将我的收藏中的所有文件按总和排序(顶部最大金额的文件......)。

对于示例数据,它应该返回如下内容:

{
 id: "299",
 sales : {
     '2014-05-23': {
        sum: 44
     },
     '2014-05-22': {
        sum: 19    
     }
 }
},
 {
 id: "213",
 sales : {
     '2014-05-23': {
        sum: 23
     },
     '2014-05-22': {
        sum: 22    
     }
 }
},

因为:总和44是最大的,因此集合中的此文档首先显示。

这可能(足够快)吗?否则我可以重新设计数据库 - 也许有人对此有建议吗?

1 个答案:

答案 0 :(得分:2)

这种表现非常糟糕,因为你正在抛弃你最好的选择,即聚合框架。

你要打破的一个重要规则是“不要将数据用作关键字”。

因此,当您使用实际上是数据点的“键”命名“子文档”时,没有简单的方法来处理它们。一般的MongoDB表示法不喜欢这样,你被迫进行JavaScript评估。与原生方法相比,这仍然是“精神上的”,但确实

更改架构,然后您可以使用聚合框架。以下是改变:

{
    "_id": 123,
    "sales": [
        { "date": ISODate("2014-05-23T00:00:00Z"), "sum": 23 },
        { "date": ISODate("2014-05-22T00:00:00Z"), "sum": 22 }
    ]
},
{
    "_id": 299,
    "sales": [
        { "date": ISODate("2014-05-22T00:00:00Z"), "sum": 19 },
        { "date": ISODate("2014-05-23T00:00:00Z"), "sum": 44 }
    ]
}

现在你的数据在一个数组中,“路径”是一致的,这意味着你可以很容易地对事物进行排序:

db.collection.find().sort({ "sales.sum": -1 })

因此,具有“最大”“sales.sum”值的文档将是第一个。

如果给出上面的例子,你想用最大的“sales.sum”“排序”内部数组元素,那么你可以使用聚合框架:

db.collection.aggregate([
    { "$unwind": "$sales" },
    { "$sort": { "_id": 1, "sales.sum": -1 } },
    { "$group": {
        "_id": "$_id",
        "sales": { "$push": "$sales" }
    }},
    { "$sort": { "sales.sum": -1 } }
])

使用mapReduce的JavaScript评估可以通过这种方式处理您当前的文档,但不要这样做,因为它会慢得多。