MongoDb-Aggregate:如何获得单个未分组记录的总计?
假设我们有如下文件:MongoDb-Aggregate:如何获得单个未分组记录的总计?,mongodb,Mongodb,假设我们有如下文件: { type: "hourly", amount: 100 }, { type: "flat", amount: 350 }, { type: "hourly", amount: 200 }, { type: "payment", amount: 100 }, { type: "payment", amount: 200 } 在管道中的某个地方,我想累积每个“类型”的总计。连同所有单个记录,我想知道我们的总计如下所示: hourly: $300 flat: $35
{ type: "hourly", amount: 100 },
{ type: "flat", amount: 350 },
{ type: "hourly", amount: 200 },
{ type: "payment", amount: 100 },
{ type: "payment", amount: 200 }
在管道中的某个地方,我想累积每个“类型”的总计。连同所有单个记录,我想知道我们的总计如下所示:
hourly: $300
flat: $350
payment: $300
myAggregate.push({
"$group": {
"_id": null, //"$transactionType",
"documents": { "$push": "$$ROOT" },
"hourlyTotal": {"$sum": "$hourlyAmount"},
"flatTotal" : {"$sum": "$flatAmount"},
"paymentTotal" : {"$sum": "$paymentAmount"},
"expenseTotal" : {"$sum": "$expenseAmount"},
"creditTotal" : {"$sum": "$creditAmount"},
"debitTotal" : {"$sum": "$debitAmount"},
}
});
我已经研究了$add和$sum,它们似乎对为给定记录添加字段很有用,而不是用于累计总计
到目前为止,我的聚合过滤了我想要的所有记录,并且没有使用分组。我不想把这些记录分组。我需要个人记录和总数
我相信如果我必须对$group-可能是$push-将单个记录放入一个数组以将其与所有其他记录一起取出,则$push命令可能是相关的。请看下面的答案:
在我的例子中,我有一个聚合,没有收集任何总数,如下所示。对于每个返回的文档,都有一个“类型”字段(例如,“小时”、“单位”、“付款”)
“myAggregate”是什么样子的,以便累计总计并返回所有单个(未分组)记录
深思熟虑后:如果“手动”遍历记录以获得总数对我来说同样有效,那么我可以做到。我认为MongoDb做这件事一定会更有效率,因为他们费心去做这些特性
编辑1:
以下是如何根据Veeram的建议添加“myAggregate”:
// Do we need to get only records which match the matter's contactId?
if (query2 != "") {
myAggregate.push( { $match: query2 } );
}
// Get grand totals.
myAggregate.push({ "$group": { "_id": "$transactionType",
"documents": { "$push": "$$ROOT" },
"grandtotal": {"$sum":"$amount"}
}
});
在Veeram的帮助下,我通过在他建议的
小组
阶段之前添加项目
阶段来获得总数。我还将组
的id设置为null(根据),以避免将所有文档分为组
$project: {
_id: 1,
firmId: 1,
... plus, a bunch more fields.
// Project some fields to allow totaling by transactionType.
hourlyAmount: { $cond: { if: { $eq: ["$transactionType", "hourly"] }, then: "$amount", else: 0 } },
flatAmount: { $cond: { if: { $eq: ["$transactionType", "flat"] }, then: "$amount", else: 0 } },
paymentAmount: { $cond: { if: { $eq: ["$transactionType", "payment"] }, then: "$amount", else: 0 } },
expenseAmount: { $cond: { if: { $eq: ["$transactionType", "expense"] }, then: "$amount", else: 0 } },
creditAmount: { $cond: { if: { $eq: ["$transactionType", "credit"] }, then: "$amount", else: 0 } },
debitAmount: { $cond: { if: { $eq: ["$transactionType", "debit"] }, then: "$amount", else: 0 } }
}
然后,根据Veeram,我分组如下:
hourly: $300
flat: $350
payment: $300
myAggregate.push({
"$group": {
"_id": null, //"$transactionType",
"documents": { "$push": "$$ROOT" },
"hourlyTotal": {"$sum": "$hourlyAmount"},
"flatTotal" : {"$sum": "$flatAmount"},
"paymentTotal" : {"$sum": "$paymentAmount"},
"expenseTotal" : {"$sum": "$expenseAmount"},
"creditTotal" : {"$sum": "$creditAmount"},
"debitTotal" : {"$sum": "$debitAmount"},
}
});
它工作得很好,所有内容都作为一个包含单个元素的数组返回。请注意,“documents”是数组元素的一个属性,因此它们可以被
[0]
.documents引用。我的所有个人总计都在那里(例如,arrayElements>[0].hourlyTotal
)。您可以添加{“$group”:{“\u id”:“$type”,“documents”:{“$push”:“$$ROOT”},“grandtotal”:{$sum:$amount”}
作为最后一步。更多@Veeram,现在似乎是我学习如何正确构建表达式的时候了。我正在阅读关于的部分,但我不太明白它们是如何组合在一起的。事实上,我引用的关于表达式的部分根本不包含任何示例。你在上面使用了相当多的表达,我需要一个好的参考来理解每一个。例如,您没有在$sum周围包含引号。对于这样的建筑表达有什么好的参考吗?我只是错过了。当您引用文档字段并使用嵌入的属性名称时,这很重要。无论如何都要使用引号。读取[$group](),并有一些不同累加器的示例。$$ROOT是一个系统变量,它提供对当前文档的访问。@Veeram。谢谢我刚刚有机会尝试一下,看看结果如何。我看到1个数组[]和1个元素。第一个元素的id为:“hourly”,documents:,grandtotal:1235。结果不包括type==“flat”或任何其他类型的元素。即使为每种类型添加了额外的元素,我的结果仍将分组。我希望所有的结果都按自然顺序或任何排序顺序进行,而不需要分组。如果放弃分组并遍历所有元素以求和它们的数量对我来说同样有效,那么我可以这样做。请告诉我。不完全确定为什么只有一种类型出现。我需要查看完整的聚合查询以及用于运行代码的数据。关于分组问题:所以mongodb将数据从一个阶段传递到另一个阶段$group
stage就像sql group要求您选择下一阶段所需的所有数据一样。如果您希望将数据展平,使每个小时文档包含相同的总计,您可以{$unwind:$document”}
并在末尾添加$sort
阶段,以向输出文档添加顺序。关于效率:您可以尝试这两种方法并比较指标。