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

使用Mongoose Aggregate查询多层嵌套数组的技术咨询

使用MongoDB Aggregate实现嵌套关联查询

针对你的需求,我们可以通过MongoDB的聚合管道(Aggregation Pipeline),结合$lookup和$map操作实现嵌套数组的关联查询,最终返回你需要的嵌套结构数据。

前提准备

假设你已经通过Mongoose定义了对应的Model:

const User = mongoose.model('User', userSchema);
const Task = mongoose.model('Task', taskSchema);
const Subtask = mongoose.model('Subtask', subtaskSchema);

完整聚合查询代码

User.aggregate([
  // 第一步:关联Task集合,将tasks数组中的ObjectId替换为完整Task文档
  {
    $lookup: {
      from: 'tasks', // 对应Task模型的集合名称(Mongoose默认转为复数小写)
      localField: 'tasks',
      foreignField: '_id',
      as: 'tasks'
    }
  },
  // 第二步:遍历每个Task,关联对应的Subtask集合
  {
    $set: {
      tasks: {
        $map: {
          input: '$tasks',
          as: 'task',
          in: {
            // 保留当前Task的所有字段
            ...'$$task',
            // 将当前Task的subtasks ObjectId数组替换为完整Subtask文档
            subtasks: {
              $lookup: {
                from: 'subtasks', // 对应Subtask模型的集合名称
                localField: '$$task.subtasks',
                foreignField: '_id',
                as: 'subtasks'
              }
            }
          }
        }
      }
    }
  }
])
.then(users => {
  // 输出符合要求的嵌套结构数据
  console.log(JSON.stringify(users, null, 2));
})
.catch(err => {
  console.error('查询失败:', err);
});

代码说明

  1. 第一层$lookup:将User文档中tasks数组的ObjectId列表,替换为来自tasks集合的完整Task文档数组。
  2. $map + 嵌套$lookup:通过$map遍历每个Task文档,对每个Task的subtasks字段执行嵌套的$lookup,将Subtask的ObjectId数组替换为完整的Subtask文档数组,同时保留Task原有的所有字段。

查询单个用户的扩展

如果只需要查询特定用户的数据,只需在聚合管道开头添加$match阶段:

User.aggregate([
  { $match: { _id: mongoose.Types.ObjectId('目标用户ID') } }, // 替换为实际用户ID
  // 后续的$lookup和$set步骤同上
])

注意事项

  • 确保你的MongoDB版本在3.6及以上,因为表达式中嵌套使用$lookup是3.6版本开始支持的特性。
  • 集合名称需与Mongoose自动生成的一致(默认将Model名转为复数小写),如果你的集合名称自定义过,需替换为实际名称。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 07:51:10