我是Mongodb和NoSQL的新手,我正在尝试使用mongodbs聚合函数来聚合来自一个集合的数据以插入到另一个集合中。原始集合的一个例子是:
原创收藏品
{
supplier: 'aldi',
timestamp: '1492807458',
user: 'eddardstark@gmail.com',
hasBeenAggregated:false,
items:[{
name: 'butter',
supplier: 'aldi',
expiry: '1492807458',
amount: 454,
measureSymbol: 'g',
cost: 2.19
},{
name: 'milk',
supplier: 'aldi',
expiry: '1492807458',
amount: 2000,
measureSymbol: 'ml',
cost: 1.49
}]
}
我想要实现的输出的一个例子是:
新收藏
{
user:'eddardstark@gmail.com',
amount: 3.68,
isIncome: false,
title: 'food_shopping',
timestamp: '1492807458'
}
我使用的聚合函数是:
聚合
var result = db.runCommand({
aggregate: 'food_transactions',
pipeline: [
{$match: {hasBeenAggregated: false}},
{$unwind: '$items'},
{$group:{_id: '$_id',amount:{$sum: '$items.cost'}}},
{$project: {
_id:0,
user:1,
amount:1,
isIncome: {$literal: false},
title:{$literal: 'food_shopping'},
timestamp:1
}}
]
});
printjson(result)
此聚合函数不会返回user
或timestamp
字段。相反,我得到以下输出:
输出
{
"amount" : 3.6799999999999997,
"isIncome" : false,
"title" : "food_shopping"
}
如果我没有对结果进行分组并在$project
阶段执行计算,那么这些字段都会正确投影,但显然,为{{1}中的每个子文档创建了一个新文档数组,而不是失败聚合的目的。
我做错了什么?
答案 0 :(得分:2)
更新您的$group
管道,以包含您希望在管道中进一步投射的所有字段。
要包含用户字段,您可以使用$first
{$group:{_id: '$_id', user:{$first:'$user`}, amount:{$sum: '$items.cost'}}},
此外,如果你是3.4版本,你可以简化你的聚合到下面。
使用$reduce
汇总单个文档中的所有item
费用。对于所有文档,您可以在$group
之后添加$reduce
。
db.collection.aggregate([
{$match: {hasBeenAggregated: false}},
{$project: {
_id:0,
user:1,
amount: {
$reduce: {
input: "$items",
initialValue: 0,
in: { $add : ["$$value", "$$this.cost"] }
}
},
isIncome: {$literal: false},
title:{$literal: 'food_shopping'},
timestamp:1
}}
])