MongoDB聚合查询:关联父文档数组子文档并匹配子文档字段
MongoDB聚合关联子文档并筛选指定字段值的解决方案
错误原因
你写的代码里,$lookup的pipeline内部无法直接访问父文档的shopItems数组,直接写_id: { $in: '$shopItems' }时,MongoDB会把'$shopItems'当成字符串而非数组,所以抛出$in needs an array的错误。
修正后的聚合代码
const result3 = await Shop.aggregate([ { $match: { _id: mongoose.Types.ObjectId('623ae52ba5b1af0004e1c4ec'), }, }, { $lookup: { from: ShopItem.collection.collectionName, // 把父文档的shopItems数组传递给pipeline let: { shopItemIds: '$shopItems' }, pipeline: [ { $match: { $expr: { // 同时满足两个条件:_id在父文档的shopItems里,且kidFriendly为false $and: [ { $in: ['$_id', '$$shopItemIds'] }, { $eq: ['$kidFriendly', false] } ] } } } ], as: 'adultOnlyItems', }, }, ]);
代码说明
$match阶段:先筛选出目标Shop文档,减少后续处理的数据量。$lookup阶段:let:定义变量shopItemIds,将父文档的shopItems数组传递到pipeline内部,引用时用$$前缀。pipeline里的$match使用$expr,允许在查询中使用聚合表达式,结合$and同时匹配两个条件:$in判断子文档的_id是否在父文档的shopItems数组中$eq匹配kidFriendly为false的子文档
as:将匹配到的子文档存入adultOnlyItems字段返回。
预期结果
运行后会得到目标Shop的文档,其中adultOnlyItems数组包含两个符合条件的ShopItem:
[ { _id: ObjectId('623ae52ba5b1af0004e1c4ec'), shopItems: [ObjectId('631e6b133b688a0004a17265'), ObjectId('62f4cc974a255f00044c01b5'), ObjectId('625ffc48eec7b20004c9294c')], adultOnlyItems: [ { _id: ObjectId('62f4cc974a255f00044c01b5'), itemName: "Alcohol", kidFriendly: false }, { _id: ObjectId('625ffc48eec7b20004c9294c'), itemName: "Glass Vase", kidFriendly: false } ] } ]
内容的提问来源于stack exchange,提问作者Dashiell Rose Bark-Huss
相关产品推荐
相关产品推荐

