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

MongoDB聚合查询嵌套数组对象:$lookup结果格式修正需求

MongoDB 实现嵌套数组元素的$lookup关联

直接用localField: 'positions.position_id'做关联会把原数组转成对象,要给数组每个元素嵌入对应的详情,可采用以下两种方案:

场景还原

原projects集合数据:

[
  {
    "name": "projectName1",
    "positions": [
      {
        "position_id": "63d78e5096109914dc963431",
        "use": true,
        "wage": 0,
        "default": true
      },
      {
        "position_id": "63d78e5096109914dc963433",
        "use": true,
        "wage": 0,
        "default": true
      }          
    ]
  }      
]

关联的positions集合数据:

[
  {
    "_id": "63d78e5096109914dc963431",
    "field": "electrical",
    "regularName": "elc"
  },
  {
    "_id": "63d78e5096109914dc963433",
    "field": "mechanic",
    "regularName": "mec"
  }
]

推荐方案(MongoDB 3.6+)

用$map遍历数组,结合子查询版$lookup,无需拆分合并,效率更高:

db.projects.aggregate([
  {
    $addFields: {
      positions: {
        $map: {
          input: "$positions",
          as: "pos",
          in: {
            $mergeObjects: [
              "$$pos",
              {
                positionDetails: {
                  $arrayElemAt: [
                    {
                      $lookup: {
                        from: "positions",
                        localField: "$$pos.position_id",
                        foreignField: "_id",
                        as: "temp"
                      }
                    },
                    0
                  ]
                }
              }
            ]
          }
        }
      }
    }
  }
])

逻辑说明

  • $map遍历每个positions元素,通过$mergeObjects将原元素与关联结果合并
  • 由于$lookup默认返回数组,用$arrayElemAt取第一个元素转为单个对象,匹配预期的详情结构

兼容旧版本方案

若使用MongoDB版本低于3.6,可通过拆分数组再合并的方式实现:

db.projects.aggregate([
  // 拆分数组,保留空数组的文档
  { $unwind: { path: "$positions", preserveNullAndEmptyArrays: true } },
  // 关联详情
  {
    $lookup: {
      from: "positions",
      localField: "positions.position_id",
      foreignField: "_id",
      as: "positions.positionDetails"
    }
  },
  // 把数组转成单个对象
  {
    $addFields: {
      "positions.positionDetails": { $arrayElemAt: ["$positions.positionDetails", 0] }
    }
  },
  // 按原文档_id合并数组
  {
    $group: {
      _id: "$_id",
      name: { $first: "$name" },
      positions: { $push: "$positions" }
    }
  }
])

注意事项

  • 必须添加preserveNullAndEmptyArrays: true,否则没有positions的文档会被过滤掉

内容的提问来源于stack exchange,提问作者Mehdi M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 23:25:57