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

如何基于键值对合并MongoDB中的JSON对象(关联Review与Launch)

合并MongoDB两个集合的查询结果

现有根据userId查询Review集合的函数:

async function getReviewsByUserId (req, res) {
  const { userId } = req.params

  const reviews = await Review.find({ userId }).lean() || []

  return res.status(200).send(reviews.reverse())
}

Review集合的文档结构示例:

{
    "_id" : ObjectId("1263b55ef2cdd3ebb0654d1dd"),
    "launchId" : "7fb83b40-7c6f-4099-aaed-fe9d0dc03111",
    "userId" : "1",
}
{
    "_id" : ObjectId("6355565cf5ef2cddebb065584"),
    "launchId" : "12b53940-136f-3399-aaed-fe9d0dc05473",
    "userId" : "7fb83b40-7c6f-4099-aaed-fe9d0dc03112",
}

需要将每个Review文档中的launchId与Launch集合中对应的文档关联,把Launch数据合并到对应的Review对象里。Launch集合文档示例:

{
    "_id" : "12b53940-136f-3399-aaed-fe9d0dc05473",
    "name" : "The Park",
}

期望最终输出结构:

{
    "_id" : ObjectId("1263b55ef2cdd3ebb0654d1dd"),
    "launchId" : "7fb83b40-7c6f-4099-aaed-fe9d0dc03111",
    "userId" : "1",
}
{
    "_id" : ObjectId("6355565cf5ef2cddebb065584"),
    "launchId" : "12b53940-136f-3399-aaed-fe9d0dc05473",
    "userId" : "7fb83b40-7c6f-4099-aaed-fe9d0dc03112",
    "launch": {
        "_id" : "12b53940-136f-3399-aaed-fe9d0dc05473",
        "name" : "The Park",
    }
}

方案一:MongoDB聚合查询(推荐,性能更优)

直接在数据库层面完成关联,减少内存处理和数据库请求次数:

async function getReviewsByUserId(req, res) {
  const { userId } = req.params;

  const reviews = await Review.aggregate([
    // 筛选指定userId的评论
    { $match: { userId } },
    // 关联Launch集合,通过launchId匹配Launch的_id
    {
      $lookup: {
        from: "launches", // 替换为你的Launch集合实际名称
        localField: "launchId",
        foreignField: "_id",
        as: "launch"
      }
    },
    // 将launch数组转为单个对象,保留无对应Launch的评论
    { $unwind: { path: "$launch", preserveNullAndEmptyArrays: true } },
    // 替代reverse(),直接在数据库层面倒序排序
    { $sort: { _id: -1 } }
  ]);

  return res.status(200).send(reviews);
}

方案二:代码层面合并(适合简单场景)

先批量查询数据,再在内存中完成合并:

async function getReviewsByUserId(req, res) {
  const { userId } = req.params;

  // 查询指定userId的评论
  const reviews = await Review.find({ userId }).lean() || [];
  if (!reviews.length) return res.status(200).send([]);

  // 提取所有去重的launchId,批量查询对应Launch
  const launchIds = [...new Set(reviews.map(r => r.launchId))];
  const launches = await Launch.find({ _id: { $in: launchIds } }).lean() || [];

  // 将Launch转为以_id为键的映射表,提升查找效率
  const launchMap = launches.reduce((map, launch) => {
    map[launch._id] = launch;
    return map;
  }, {});

  // 合并数据到对应Review中
  const mergedReviews = reviews.map(review => ({
    ...review,
    launch: launchMap[review.launchId] || undefined
  }));

  return res.status(200).send(mergedReviews.reverse());
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 23:05:32