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

Mongoose中unwind后如何合并数组元素并处理点赞用户关联

解决方案

你的问题核心是处理帖子点赞用户时,破坏了allPostsCombined的结构。正确的做法是在拆分出单个帖子后,单独处理每个帖子的点赞用户数据,再重新组装回帖子数组,最后聚合回用户文档。

修改后的聚合管道如下:

const userWithAllPosts = await User.aggregate([
  {
    $match: {
      _id: new mongoose.Types.ObjectId(id),
    },
  },
  // 获取自己的帖子(包含评论用户信息)
  {
    $lookup: {
      from: "posts",
      localField: "_id",
      foreignField: "userId",
      pipeline: [
        {
          $lookup: {
            from: "comments",
            localField: "_id",
            foreignField: "postId",
            pipeline: [
              {
                $lookup: {
                  from: "users",
                  localField: "commenterId",
                  foreignField: "_id",
                  as: "commentOwner",
                },
              },
              // 把评论用户数组拆成单个对象(可选,按需调整)
              { $unwind: "$commentOwner" }
            ],
            as: "postComments",
          },
        },
      ],
      as: "myPosts",
    },
  },
  // 获取好友的帖子(包含评论用户信息)
  {
    $lookup: {
      from: "posts",
      localField: "friends",
      foreignField: "userId",
      pipeline: [
        {
          $lookup: {
            from: "comments",
            localField: "_id",
            foreignField: "postId",
            pipeline: [
              {
                $lookup: {
                  from: "users",
                  localField: "commenterId",
                  foreignField: "_id",
                  as: "commentOwner",
                },
              },
              { $unwind: "$commentOwner" }
            ],
            as: "postComments",
          },
        },
      ],
      as: "allFriendsPosts",
    },
  },
  // 合并自己和好友的帖子
  {
    $set: {
      allPostsCombined: { $concatArrays: ["$myPosts", "$allFriendsPosts"] },
    },
  },
  // 拆分出单个帖子,便于处理每个帖子的点赞
  { $unwind: "$allPostsCombined" },
  // 处理单个帖子的点赞用户:先拆分likes数组,保留无点赞的帖子
  {
    $unwind: {
      path: "$allPostsCombined.likes",
      preserveNullAndEmptyArrays: true,
    },
  },
  // 根据点赞用户ID获取用户信息
  {
    $lookup: {
      from: "users",
      localField: "allPostsCombined.likes",
      foreignField: "_id",
      as: "likeUser",
    },
  },
  // 拆分点赞用户数组(lookup返回的是数组)
  { $unwind: { path: "$likeUser", preserveNullAndEmptyArrays: true } },
  // 重新分组,把同一个帖子的点赞用户合并成数组
  {
    $group: {
      _id: {
        userId: "$_id",
        postId: "$allPostsCombined._id",
      },
      // 保留用户的基本信息
      name: { $first: "$name" },
      email: { $first: "$email" },
      bio: { $first: "$bio" },
      livesIn: { $first: "$livesIn" },
      profilePic: { $first: "$profilePic" },
      coverPic: { $first: "$coverPic" },
      createdAt: { $first: "$createdAt" },
      updatedAt: { $first: "$updatedAt" },
      // 保留帖子的其他字段
      post: { $first: "$allPostsCombined" },
      // 收集点赞用户信息
      likeUsers: { $push: "$likeUser" },
    },
  },
  // 把点赞用户数组添加到帖子对象中,过滤空值
  {
    $set: {
      "post.likeUsers": {
        $filter: {
          input: "$likeUsers",
          cond: { $ne: ["$$this", null] },
        },
      },
    },
  },
  // 按帖子创建时间倒序排序
  { $sort: { "post.createdAt": -1 } },
  // 最终分组回用户,把处理好的帖子合并成数组
  {
    $group: {
      _id: "$_id.userId",
      name: { $first: "$name" },
      email: { $first: "$email" },
      bio: { $first: "$bio" },
      livesIn: { $first: "$livesIn" },
      profilePic: { $first: "$profilePic" },
      coverPic: { $first: "$coverPic" },
      createdAt: { $first: "$createdAt" },
      updatedAt: { $first: "$updatedAt" },
      allPostsCombined: { $push: "$post" },
    },
  },
]);

关键细节说明:

  • 保留无点赞帖子:用preserveNullAndEmptyArrays: true避免没有点赞的帖子被过滤掉。
  • 精准分组:通过userId+postId的嵌套ID分组,确保同一个帖子的点赞用户被正确合并成数组。
  • 清理空数据:用$filter移除点赞数组中的null值,避免空对象干扰后续逻辑。
  • 结构还原:最终的$group操作确保用户文档结构和原始需求一致,每个帖子新增likeUsers属性存储点赞用户的完整信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 12:10:22