1

作为查找的结果,我有以下记录集:

[{ 'programming': 7 },
{ 'programming': 9 },
{ 'programming': 6 },
{ 'programming': 10 },
{ 'music': 1 },
{ 'music': 2 },
{ 'music': 3 },
{ 'music': 4 }]

我想按键对它们进行分组并对值求和,以获得:

[{'programming': 32},
 {'music': 10}]

按值对它们进行排序(在这种情况下,首先是编程,然后是音乐)并限制为 3(如果有programming 32,和music 10,则只返回,和.shopping 3lifestyle 1programmingshoppinglifestyle

如何聚合这些数据?我应该使用 mapreduce、聚合还是简单地分组?如果是这样,如何通过字典键告诉组到组?

谢谢

4

3 回答 3

6

希望这会有所帮助。

测试:v3.6.5

db.cname.aggregate([
{
    $project:
    {
        _id: 0
    }
},
{
    $project:
    {
        "o":
        {
            $objectToArray: "$$ROOT"
        }
    }
},
{
    $unwind: "$o"
},
{
    $group:
    {
        _id: "$o.k",
        value:
        {
            $sum: "$o.v"
        }
    }
}])

输出

{ "_id" : "music", "value" : 10 }

{ "_id" : "programming", "value" : 32 }
于 2018-09-15T21:52:26.853 回答
1

虽然我建议不按键分组的方式使用@gustavohenke 的路线,但您可以使用 mapreduce 来完成(我想不出一种使用聚合的方法,这将是更直接的路线)

> var mapFunction = function() {
     for(var key in this) { 
        if(key!='_id') emit(key, this[key]); 
     } 
  };

> var reduceFunction = function(key, values) { return Array.sum(values); }

> db.data.mapReduce(mapFunction, reduceFunction, { out: 'bop' })
{
    "result" : "bop",
    "timeMillis" : 47,
    "counts" : {
        "input" : 8,
        "emit" : 8,
        "reduce" : 2,
        "output" : 2
    },
    "ok" : 1,
}
> db.bop.find().sort({value: -1}).limit(3)
{ "_id" : "programming", "value" : 32 }
{ "_id" : "music", "value" : 10 }
> 
于 2013-05-28T11:35:27.597 回答
1

按键操作会破坏查询的可维护性。

我最好的建议是:创建另一个键,比如说skill(这将是文档分组键)和一个名为value.
然后你会得到一个有点像这样的查询:

db.skills.aggregate([{
  $group: {
    _id: "$skill",
    value: { $sum: "$value" }
  }
}])
于 2013-05-28T11:28:32.037 回答