我有这个集合
{
"_id" : ObjectId("54f46f18c36dcc206d0cec38"),
"project" : 23123,
"title" : "Change of windows",
"description": "Change to better windows on building A"
"costs":[
{
category: 'Produktionskostnad',
value: 3000
},
{
category: 'Projekteringskostnad',
value: 2000
},
{
category: 'Overhead',
value: 1000
}
],
"energySaving" : [
{
"energy" : "electricity",
"type" : "lighting",
"value" : 24324
},
{
"energy" : "electricity",
"type" : "equipment",
"value" : 24324
},
{
"energy" : "electricity",
"type" : "fans",
"value" : 24324
},
{
"energy" : "electricity",
"type" : "distribution",
"value" : 24324
},
{
"energy" : "electricity",
"type" : "chiller",
"value" : 24324
},
{
"energy" : "electricity",
"type" : "other",
"value" : 24324
}
]
}
我需要一个汇总来计算总成本和总节能量。
要获得保存,我有这个查询:
db.collection.aggregate( [
{ $unwind: "$energySaving" },
{
$group: {
_id: {
title: '$title',
description: '$description'
},
totalEnergySaving: { $sum: '$energySaving.value' }
}
}
]);
但是如何计算同一查询中的总费用?我不能在同一个查询中添加$ unwind cost。我可以以某种方式“重置”$ group并再次查询查询吗?
答案 0 :(得分:5)
在现代MongoDB版本中,我们只执行一个$group
,因为我们可以将数组项直接传递给$sum
,并使用“数组求和”和“累加器”连续的“双”表示法: / p>
db.collection.aggregate([
{ "$group": {
"_id": {
"title": "$title",
"description": "$description"
},
"totalCosts": { "$sum": { "$sum": "$costs.value" } },
"totalEnergySaving": { "$sum": { "$sum": "$energySaving.value" } }
}}
])
这需要一些杂耍才能正确完成,但描述它的最佳方法是“首先处理每个文档的分组”然后“稍后对总计进行分组”:
db.collection.aggregate([
// Do cost per document
{ "$unwind": "$costs" },
{ "$group": {
"_id": "$_id",
"title": { "$first": "$title" },
"description": { "$first": "$description" },
"totalCosts": { "$sum": "$costs.value" },
"energySaving": { "$first": "$energySaving" }
}},
// Do energy saving per document
{ "$unwind": "$energySaving" },
{ "$group": {
"_id": "$_id",
"title": { "$first": "$title" },
"description": { "$first": "$description" },
"totalCosts": { "$first": "$totalCosts" },
"totalEnergySaving": { "$sum": "$energySaving.value" }
}},
// Now sum the real grouping
{ "$group": {
"_id": {
"title": "$title",
"description": "$description"
},
"totalCosts": { "$sum": "$totalCosts" },
"totalEnergySaving": { "$sum": "$totalEnergySaving" }
}}
])
通过处理数组值每个文档的单个值,并通过展开和分组“一次一个数组”来避免每个数组成员的项目复制,您可以形成一个基础来实现您实际的单一分组想。
因此,当您$unwind
数组时,您将获得文档的多个副本,每个数组成员现在在每个文档副本中表示为单数值。你不想在这里做的是$unwind
另一个阵列,而你已经有一个没有伤口,因为根据阵列有多少成员,它会以相同的方式创建文档的“更多副本”。 / p>
此时使用$group
返回文档_id
值可确保我们仅处理最初“未受伤”的文档的原始部分。像$sum
这样的普通分组操作符仍然适用,但是$first
可以用来在“数组之外”只提取那些复制字段值中的“只有一个”并且几乎将文档返回到它的“原始形式” “对于您要保留的字段,以及您有意从数组内容聚合的任何内容。
对你想要的每个数组重复一次,然后转到另一个$group
语句,这次使用你之前创建的新的奇异求和值,一次只加一个文档。
这是在任何级别的分组中添加多个数组项的过程。当然,如果唯一的分组是在文档级别进行的,那么你可以在对每个数组进行分组后放弃,或者确实接受在客户端代码中做得更好。