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

MongoDB聚合:如何将关联数据转为根文档并保留父文档数据?

MongoDB聚合管道实现:将评论、点赞与对应帖子关联为独立文档

需求说明

现有posts、comments、likes三个集合,需构建聚合管道,让每条评论、每条点赞都作为独立文档返回,且每个文档包含对应的完整帖子数据,同时关联评论/点赞发起者的用户信息。

集合结构示例

posts集合

[
  {
    "_id":"62a25c932c38e92bdcd32094",
    "text": "Text to be written by the creator of the post.",
    "userId": "621b814eed5b141c19c2d34b",
    "createdAt": { "$date": "2022-06-09T20:48:19.528Z" }
  }
]

comments集合

[
  {
    "_id": { "$oid": "62a3677843c638676e126815" },
    "postId": { "$oid": "62a25c932c38e92bdcd32094" },
    "text": "Text to be written by the creator of the comment.",
    "userId": { "$oid": "6255d5d7eb15644e44b84240" },
    "createdAt": { "$date": "2022-06-10T15:47:04.429Z" }
  }
]

likes集合

[
  {
    "_id": { "$oid": "62a30565f8ded22defc7bb78" },
    "postId": { "$oid": "62a25c932c38e92bdcd32094" },
    "userId": { "$oid": "6255d5d7eb15644e44b84240" },
    "createdAt": { "$date": "2022-06-10T08:48:37.203Z" }
  }
]

聚合管道解决方案

假设存在users集合存储用户信息(包含_id和name字段),以下是完整的聚合管道:

db.posts.aggregate([
  // 关联当前帖子的所有评论
  {
    $lookup: {
      from: "comments",
      localField: "_id",
      foreignField: "postId",
      as: "comments"
    }
  },
  // 关联当前帖子的所有点赞
  {
    $lookup: {
      from: "likes",
      localField: "_id",
      foreignField: "postId",
      as: "likes"
    }
  },
  // 为评论、点赞标记类型,方便后续合并拆分
  {
    $project: {
      _id: 1,
      text: 1,
      userId: 1,
      createdAt: 1,
      comments: {
        $map: {
          input: "$comments",
          as: "c",
          in: {
            type: "comment",
            data: "$$c"
          }
        }
      },
      likes: {
        $map: {
          input: "$likes",
          as: "l",
          in: {
            type: "like",
            data: "$$l"
          }
        }
      }
    }
  },
  // 合并评论和点赞数组
  {
    $project: {
      postData: {
        _id: "$_id",
        text: "$text",
        userId: "$userId",
        createdAt: "$createdAt"
      },
      activities: { $concatArrays: ["$comments", "$likes"] }
    }
  },
  // 将合并后的数组拆分为独立文档
  { $unwind: "$activities" },
  // 关联用户信息
  {
    $lookup: {
      from: "users",
      localField: "activities.data.userId",
      foreignField: "_id",
      as: "userInfo"
    }
  },
  // 提取用户信息(取第一个匹配项)
  { $addFields: { user: { $arrayElemAt: ["$userInfo", 0] } } },
  // 整理最终文档结构
  {
    $project: {
      _id: "$postData._id",
      text: "$postData.text",
      userId: "$postData.userId",
      createdAt: "$postData.createdAt",
      comment: {
        $cond: {
          if: { $eq: ["$activities.type", "comment"] },
          then: {
            _id: "$activities.data._id",
            user: { name: "$user.name" }
          },
          else: "$$REMOVE"
        }
      },
      like: {
        $cond: {
          if: { $eq: ["$activities.type", "like"] },
          then: {
            _id: "$activities.data._id",
            user: { name: "$user.name" }
          },
          else: "$$REMOVE"
        }
      }
    }
  }
])

管道阶段解释

  1. $lookup(关联评论/点赞):分别从comments和likes集合中获取当前帖子对应的所有评论、点赞数据。
  2. $map(标记类型):为每条评论、点赞添加类型标识,方便后续合并后区分类型。
  3. $concatArrays(合并数组):将评论数组和点赞数组合并为一个统一的活动数组。
  4. $unwind(拆分文档):把活动数组拆分成独立文档,每条评论/点赞对应一个文档。
  5. $lookup(关联用户):根据评论/点赞的userId从users集合获取用户信息。
  6. $addFields(提取用户):从用户信息数组中取出第一个匹配的用户数据。
  7. $project(整理结构):根据活动类型,动态生成comment或like字段,同时保留帖子的核心数据,最终输出符合需求的文档结构。

预期输出

[
  {
    "_id":"62a25c932c38e92bdcd32094",
    "text": "Text to be written by the creator of the post.",
    "userId": "621b814eed5b141c19c2d34b",
    "comment":{
        "_id": { "$oid": "62a3677843c638676e126815" },
        "user":{ "name": "John" }
    },
    "createdAt": { "$date": "2022-06-09T20:48:19.528Z" }
  },
  {
    "_id":"62a25c932c38e92bdcd32094",
    "text": "Text to be written by the creator of the post.",
    "userId": "621b814eed5b141c19c2d34b",
    "like":{
        "_id": { "$oid": "62a30565f8ded22defc7bb78" },
        "user":{ "name": "John" }
    },
    "createdAt": { "$date": "2022-06-09T20:48:19.528Z" }
  }
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 03:06:38