我有发票,每张发票都包含一个项目列表。每个项目都有(除其他外)以下字段:
- 姓名
- 数量
- 全部的
每张发票(除其他外)都有以下字段:
- _ID
- 创建
- 项目
发票存在于一个专门的 Mongo 集合中,称为invoices。
我想获取包含指定项目的所有发票,其中每张发票需要返回以下信息:
- _ID
- 创建
- 数量(给定项目的)
- 总计(给定项目的)
让我们将元组 <id, date, qty, total> 称为发票投影。因此,结果应该是发票预测列表。
如果一张发票两次列出给定项目,则相应的发票会产生两个投影实例。如果发票根本没有列出给定项目,则该发票不会出现在结果中。
无论如何,我正在使用以下 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'}}
],
管道是这样工作的:
- 首先匹配具有给定名称的项目的所有发票。上有一个 Mongo 索引
items.name
,所以这$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 聚合管道中吗?