Joe*_*Joe 5 mongodb mongodb-query aggregation-framework
我有这个系列
{
"_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
}
]
}
Run Code Online (Sandbox Code Playgroud)
我需要一个汇总来计算总成本和总节能量.
为了得到保存我有这个查询:
db.collection.aggregate( [
{ $unwind: "$energySaving" },
{
$group: {
_id: {
title: '$title',
description: '$description'
},
totalEnergySaving: { $sum: '$energySaving.value' }
}
}
]);
Run Code Online (Sandbox Code Playgroud)
但是,如何计算同一查询中的总费用?我不能在同一个查询中添加$ unwind cost.我能以某种方式"重置"$ group并再次查询吗?
在Modern MongoDB版本中,我们只需执行一个,$group因为我们可以将数组项直接传递$sum给"数组求和"和"累加器"的"双"表示法:
db.collection.aggregate([
{ "$group": {
"_id": {
"title": "$title",
"description": "$description"
},
"totalCosts": { "$sum": { "$sum": "$costs.value" } },
"totalEnergySaving": { "$sum": { "$sum": "$energySaving.value" } }
}}
])
Run Code Online (Sandbox Code Playgroud)
这需要一些杂耍才能正确完成,但描述它的最佳方式是"首先处理每个文档的分组"然后"稍后对总计进行分组":
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" }
}}
])
Run Code Online (Sandbox Code Playgroud)
通过处理数组值每个文档的单个值,并通过展开和分组"一次一个数组"来避免每个数组成员的项目复制,您形成了实际需要的单个分组的基础.
因此,当您$unwind使用数组时,您将获得文档的多个副本,每个数组成员现在在每个文档副本中表示为单数值.你不想在这里做的是$unwind另一个阵列,而你已经有一个没有伤口,因为这将以相同的方式创建该阵列具有多少个成员的文档的"更多副本".
此时使用$group返回文档_id值可确保我们仅处理最初"未缠绕"的文档的原始部分.正常的分组操作符$sum仍然适用,但$first可以用来在"数组之外"只提取那些复制字段值中的"只有一个",并且几乎将文档返回到它要保留的字段的"原始形式".你有意从数组内容聚合的任何东西.
对你想要的每个数组重复一遍,然后转到另一个$group语句,这次使用你之前创建的新的奇异求和值,一次只加一个文档.
这是在任何级别的分组中添加多个数组项的过程.当然,如果唯一的分组是在文档级别进行的,那么你可以在对每个数组进行分组后放弃,或者确实接受在客户端代码中做得更好.