作为查找的结果,我有以下记录集:
[{ '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 3和lifestyle 1,则只返回programming、shopping和lifestyle。
如何聚合这些数据?我应该使用mapreduce,聚合还是简单的分组?如果是这样的话,如何让group按字典键分组?
谢谢
发布于 2018-09-16 05:52:27
希望这能有所帮助。
测试环境: 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 }发布于 2013-05-28 19:28:32
按键这样做会扼杀查询的可维护性。
我最好的建议是:创建另一个键,比如skill (这将是文档分组键)和一个名为value的键。
然后你会得到一个类似下面这样的查询:
db.skills.aggregate([{
$group: {
_id: "$skill",
value: { $sum: "$value" }
}
}])发布于 2013-05-28 19:35:28
虽然我建议使用@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 }
> https://stackoverflow.com/questions/16789369
复制相似问题