[英]MongoDB Aggregation - Sum value of nested arrays
I'm trying to get the sum of a specific field that's inside an array. 我试图获取数组内的特定字段的总和。 The problem is, that array is also inside another array.
问题是,该数组也位于另一个数组中。 My documents are as follow (simplified):
我的文档如下(简体):
{
"nome": "test-1"
"notas": [{
"numero_fiscal": "0001",
"valores": {
"portal": 1000,
"arquivo": 1000
},
"abatimentos": [{
"valor": 250,
"tipo": "TIPO 1"
}, {
"valor": 250,
"tipo": "TIPO 2"
}]
}, {
"numero_fiscal": "0002",
"valores": {
"portal": 2000,
"arquivo": 2000
},
"abatimentos": [{
"valor": 500,
"tipo": "TIPO 1"
}, {
"valor": 500,
"tipo": "TIPO 2"
}]
}]
}
I want my output to be something like: 我希望我的输出是这样的:
{
"_id": "resumo",
"total_notas": 2, // this is the counter for the array "notas"
"soma_portal": 3000, // this is the sum of the "valores.portal" of all "notas"
"soma_arquivo": 3000, // this is the sum of the "valores.arquivo" of all "notas"
"soma_abatimento": 1500 // this is the sum of all the "abatimentos.valor" from all the "notas"
}
I have tried the following aggregation (amongst others, but the result is always the same): 我尝试了以下聚合(以及其他聚合,但结果始终相同):
Notas.aggregate()
.match(my_query)
.unwind('notas') // unwinding 'notas' array
.group({
'_id': 'resumo',
'total_notas': { '$sum': 1 },
'abatimentos': { '$push': '$notas.abatimentos' },
'soma_portal': { '$sum': { '$notas.valores.portal' } },
'soma_arquivo': { '$sum': { '$notas.valores.arquivo' } }
})
.unwind('$abatimentos')
.group({
'_id': '$_id',
'total_notas': { '$first': '$total_notas' },
'soma_portal': { '$first': '$soma_portal' },
'soma_arquivo': { '$first': '$soma_arquivo' },
'soma_abatimento': { '$sum': '$abatimentos.valor' }
})
This gives me almost everything i want correctly, but the 'soma_abatimento' is always 0, instead of 1500 这给了我几乎所有我想要的正确信息,但是'soma_abatimento'始终为0,而不是1500
Am i on the right path? 我在正确的道路上吗? Or is this something that should not be done on the database query?
还是在数据库查询中不应该这样做?
In your current version, you need to add a double $unwind because, as you've correctly identified, after your first $group you have an array within an array. 在当前版本中,您需要添加双精度$ unwind,因为您已经正确地确定了,在第一个$ group之后,数组中有一个数组。
Here is a slightly modified version that produces the expected result. 这是一个稍作修改的版本,可以产生预期的结果。
db.Notas.aggregate([{
$unwind: "$notas"
}, {
$group: {
_id: "resumo",
total_notas: { $sum: 1 },
soma_portal: { $sum: "$notas.valores.portal" },
soma_arquivo: { $sum: "$notas.valores.arquivo" },
abatimentos: { $push: "$notas.abatimentos" }
}
}, {
$unwind: "$abatimentos"
}, {
$unwind: "$abatimentos"
}, {
$group: {
_id: "$_id",
total_notas: { $first: "$total_notas" },
soma_portal: { $first: "$soma_portal" },
soma_arquivo: { $first: "$soma_arquivo" },
soma_abatimentos: { $sum: "$abatimentos.valor" }
}
}])
If you're able to use MongoDB >= 3.4, I'd recommend a different approach that will reduce document size and obviate the need for more than one $unwind using $reduce that was added in MongoDB 3.4 如果您能够使用MongoDB> = 3.4,我建议使用另一种方法来减少文档大小,并避免使用MongoDB 3.4中添加的$ reduce进行多个$ unwind操作
db.Notas.aggregate([{
$unwind: "$notas"
}, {
$project: {
_id: 0,
portal: "$notas.valores.portal",
arquivo: "$notas.valores.arquivo",
abatimentos: {
$reduce: {
input: "$notas.abatimentos",
initialValue: 0,
in: { $add: ["$$value", "$$this.valor"] }
}
}
}
}, {
$group: {
_id: "resumo",
total_notas: { $sum: 1 },
soma_portal: { $sum: "$portal" },
soma_arquivo: { $sum: "$arquivo" },
soma_abatimentos: { $sum: "$abatimentos" }
}
}])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.