【发布时间】:2013-06-10 23:13:12
【问题描述】:
我有发票,每张发票都包含一个项目列表。每个项目都有(除其他外)以下字段:
- 姓名
- 数量
- 总计
每张发票都有(除其他外)字段:
- _id
- 已创建
- 项目
发票保存在一个专门的 Mongo 集合中,称为 invoices。
我想获取包含指定项目的所有发票,其中每张发票需要返回以下信息:
- _id
- 已创建
- 数量(给定项目的)
- 总计(给定项目的)
让我们将元组
如果一张发票两次列出给定项目,则相应的发票会产生两个投影实例。如果发票根本没有列出给定项目,则结果中不存在该发票。
无论如何,我正在使用以下 Mongo 聚合管道检索所需的投影:
pipeline = [
{$match: {'items.name': req.params.name}},
{$project: {created: 1, 'items.name': 1, 'items.qty': 1, 'items.total': 1}},
{$unwind: '$items'},
{$match: {'items.name': req.params.name}},
{$project: {created: 1, qty: '$items.qty', total: '$items.total'}}
],
管道是这样工作的:
- 首先匹配具有给定名称项目的所有发票。
items.name上有一个Mongo索引,所以这个$match是高效的。 - 发票是一个大对象,因此去掉所有字段,只留下以下结构:
{_id: ?, created: ?, items: [{name: ?, qty: ?, total: ?}, ..., {name: ?, qty: ?, total: ?}]} - 展开
items数组,现在我们有一个{_id: ?, created: ?, 'items.name': ?, 'items.qty': ?, 'items.total': ?}对象列表。 - 删除所有与给定名称不匹配的项目。
- 塑造最终发票投影。
然后通过以下代码输入发票预测的最终列表:
function prepareResult(projections) {
var res = projections.reduce(function (acc, item) {
acc.itemCount += item.qty;
acc.total += item.total;
delete item.total;
return acc;
}, {itemCount: 0, total: 0});
res.items = projections;
return res;
}
它将所有发票预测的qty 和total 字段相加,并返回一个包含预测和计算总和的新对象。 total 字段已从每个发票预测中删除,因为它只是需要的最终总和。
我的问题 - 我可以将 prepareResult 函数的逻辑移动到 Mongo 聚合管道中吗?
【问题讨论】:
标签: mongodb aggregation-framework