我有发票,每张发票都包含一个项目列表。每个项目(以及其他内容)包括以下字段:
每张发票都有(除其他外)字段:
发票存放在专门的Mongo系列中,名为发票。
我想获取包含指定商品的所有发票,每张发票需要返回以下信息:
让我们调用元组< 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'}}
],
管道的工作原理如下:
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聚合管道中吗?
答案 0 :(得分:1)
您需要在管道中添加$ group步骤。
组的_id将是你所总结的(在这种情况下是一个常数,因为你想要一个总数)。由于您要保留发票清单,可以通过$ push运算符将它们累积到数组字段中。总金额和数量的金额将以$ sum处理。
{$group : { _id : 1,
Total : { $sum : "$total" },
ItemCount : { $sum : "$qty" },
Invoices : { $push : { id : "$_id", created : "$created" }}
} }