You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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',
    },
  },
]);

代码说明

  1. $match阶段:先筛选出目标Shop文档,减少后续处理的数据量。
  2. $lookup阶段:
    • let:定义变量shopItemIds,将父文档的shopItems数组传递到pipeline内部,引用时用$$前缀。
    • pipeline里的$match使用$expr,允许在查询中使用聚合表达式,结合$and同时匹配两个条件:
      • $in判断子文档的_id是否在父文档的shopItems数组中
      • $eq匹配kidFriendly为false的子文档
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 15:26:06