我有一个电子商务服务器,其中有一个products
和一个orders
集合。
任何product
文档都包含唯一的productId
,例如prod_123
。每个order
文档都包含一个lineItems
(数组)字段,该字段返回所购买产品的productId
以及所购买的相应quantity
,例如
[{ productId: 'prod_123', quantity: 2 }, { productId: 'prod_234', quantity: 7 }, ...]
当我的客户获取他们的订单时,我希望用products
集合中的匹配产品文档填充每个lineItems
元素的productId
。
我已经编写了一个mongoDB聚合管道来实现这一点,目前为止就是这样:
const orderPipeline = [
{
$match: { customerId: 'the customer's ID' },
},
{
$lookup: {
from: 'products',
let: { productIds: '$lineItems.productId' },
pipeline: [
{ $match: { $expr: { $in: ['$productId', '$$productIds'] } } },
//*** somehow, need to add in corresponding `lineItem.quantity` here
],
as: 'products',
},
},
{ $unset: ['lineItems'] },
];
但是,正如您所看到的,虽然连接正在进行,但在删除lineItems
之前,我无法计算出如何将匹配产品的quantity
添加到连接的product
中。
如何将对应的quantity
添加到对应的匹配product
中?
1条答案
按热度按时间5anewei61#
考虑到评论中提到的额外约束,我 * 非常肯定 * 会起作用的一种方法是利用the
$zip
operator。1.执行
$lookup
,使用从其他集合检索到的信息生成数组(products
)。1.使用
$addFields
阶段作为大部分组合逻辑发生的地方。它将两个数组一起$zip
,然后$map
到$mergeObjects
,每个对都变成一个单独的对象。1.以
$unset
阶段结束,以删除原始的lineItems
字段(该字段已经合并到重新创建的products
数组中)。完整的管道如下所示:
Playground example here
乍一看,
$map
和$mergeObjects: "$$this"
可能看起来很奇怪。这是必需的,因为$zip
将生成一个数组的数组(每个数组有2个条目),如下所示:(Here is a playground link,显示压缩后但进一步处理前的输出。)
因此,我们需要将每个对象都折叠成一个对象,因此就有了
$mergeObjects
。外部数组中的每个对象都是一个数组(包含我们要合并的两个对象),这就是为什么我们可以简单地使用"$$this"
作为运算符的输入表达式。