过去几个小时我一直在摸着头,无法绕过它。也许有人可以帮忙。我有一个以下的集合。
{
"smallparts": [
{ "quantity": "10", "part": "test1" },
{ "quantity": "10", "part": "test2" }
]
},
{
"smallparts": [
{ "quantity": "10", "part": "test3" }
]
},
{
"smallparts": [
{ "quantity": "10", "part": "test1" },
{ "quantity": "10", "part": "test2" }
]
}
尝试以下内容添加数量时我无法做到。
collection.aggregate(
// Unwind the array
{ "$unwind":"$smallparts" },
// Group the products
{
"$group":
{
"_id":
{
"part": "$smallparts.part",
"total": "$smallparts.quantity",
}
},
},
我的输出是错误的。 test1和test2应为20。
{
"data": [
{
"_id": {
"part": "test3",
"total": "10"
}
},
{
"_id": {
"part": "test2",
"total": "10"
}
},
{
"_id": {
"part": "test1",
"total": "10"
}
}
]
}
我也尝试了这个,但得到一个空数组。
collection.aggregate(
//展开数组 {" $ unwind":" $ smallparts" },// Group the products { "$group": { "_id": { "part": "$smallparts.part", "total": "$smallparts.quantity", sum: { $sum: "$smallparts.quantity" } } },
感谢您的帮助。
答案 0 :(得分:2)
您遇到的问题是您不能将$sum
与字符串一起使用。您需要将数量转换为整数才能使此查询生效。
当数量为整数时,获取所有总数的总和的方法:
db.coll.aggregate([
{ $unwind : "$smallparts"},
{ $group : {
_id : "$smallparts.part" ,
sum : { $sum : "$smallparts.quantity" }
}
}]);
如果您可以控制db模式,那么这将是推荐的方法。
第二种方法是使用map-reduce重写您的查询,您可以使用parseInt
之类的JavaScript函数来转换值:
var mapFunction = function() {
for (var idx = 0; idx < this.smallparts.length; idx++) {
emit(this.smallparts[idx].part, this.smallparts[idx].quantity);
}
};
var reduceFunction = function(key, vals) {
var sum = 0;
for (var idx = 0; idx < vals.length; idx++) {
sum += parseInt(vals[idx]);
}
return sum;
};
db.coll.mapReduce(mapFunction, reduceFunction, { out : "my_mapreduce_res"});
您的地图缩减结果将存储在my_mapreduce_res
集合中。