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

如何在Mongoose中将Lookup管道的投影值查询为键值对

问题描述

当前使用Mongoose执行如下$lookup聚合查询:

{
  $lookup:{
    from:'response',
    localField:'_id',
    foreignField:'user',
    as:'dataResponse',
    pipeline:[{$project:{ resId:1, status:1 }}]
  }
}

查询返回结果示例:

{
  email: "test@test.com",
  dataResponse: [ 
    {_id: '63515eea05c8c884a33b291d', resId: '632f2d8e470895396dccefdb', status: 'IN_PROGRESS'},
    {_id: '6385ee9f451fa8879071bcde', resId: '63771adafa3b611596aaa15d', status: 'CREATED'}
  ]
}

需要将dataResponse字段从数组格式转换为以resId为键、status为值的键值对对象,最终期望结果如下:

{
  email: "test@test.com",
  dataResponse: {
    "632f2d8e470895396dccefdb": 'IN_PROGRESS',
    "63771adafa3b611596aaa15d": 'CREATED'
  }
}
实现方案

在原聚合管道的$lookup阶段之后,添加一个$set阶段,通过$map和$arrayToObject操作完成格式转换:

完整聚合管道

[
  {
    $lookup:{
      from:'response',
      localField:'_id',
      foreignField:'user',
      as:'dataResponse',
      pipeline:[{$project:{ resId:1, status:1 }}]
    }
  },
  {
    $set: {
      dataResponse: {
        $arrayToObject: {
          $map: {
            input: "$dataResponse",
            as: "item",
            in: {
              k: "$$item.resId",
              v: "$$item.status"
            }
          }
        }
      }
    }
  }
]

步骤说明

  1. $map遍历数组:将dataResponse数组中的每个元素转换为包含k(键)和v(值)的对象,其中k对应元素的resId,v对应元素的status
  2. $arrayToObject转换为对象:把$map生成的数组直接转换成键值对格式的对象
  3. $set替换字段:用转换后的对象覆盖原来的dataResponse字段

处理空数组场景(可选)

如果需要兼容dataResponse为空数组的情况,可通过$cond判断返回空对象:

{
  $set: {
    dataResponse: {
      $cond: {
        if: { $eq: ["$dataResponse", []] },
        then: {},
        else: {
          $arrayToObject: {
            $map: {
              input: "$dataResponse",
              as: "item",
              in: { k: "$$item.resId", v: "$$item.status" }
            }
          }
        }
      }
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 13:55:21