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

如何在两层map函数中使用await从MongoDB获取分类文档并修改API返回结果

问题分析与解决方法

你的代码返回undefined数组主要有两个核心问题:

  1. 外层map没有返回值:你在外层的searchResults.map里没有返回任何异步操作的结果,所以Promise.all接收的是一堆undefined的Promise,最终结果自然是全undefined的数组。
  2. 内层map的Promise未被等待:内层的item.categories.map返回的是Promise数组,但你没有用Promise.all去等待这些Promise全部完成,就算外层有返回,也只是返回一堆未resolved的Promise对象,而不是实际的分类数据。

修正后的代码

const resultArray = await Promise.all(
  searchResults.map(async (item) => {
    // 等待所有分类ID对应的查询完成,注意这里用findOne更合适(因为ID唯一)
    const categoryDocs = await Promise.all(
      item.categories.map(async (categoryId) => {
        const doc = await CategoryType.findOne({ _id: categoryId });
        // 只提取我们需要的_id和name字段
        return { _id: doc._id, name: doc.name };
      })
    );
    // 返回修改了categories字段的新对象(避免修改原item)
    return {
      ...item,
      categories: categoryDocs
    };
  })
);

关键细节说明

  • 用Promise.all包裹内层的map结果,确保所有分类查询都完成后再继续处理。
  • 把CategoryType.find改成CategoryType.findOne:因为你是根据唯一的_id查询单个分类文档,find会返回数组,而findOne直接返回单个文档对象,更符合需求。
  • 返回一个新的对象(用展开运算符...item)而不是直接修改原item,这是更安全的做法,避免意外修改原数据。
  • 明确提取_id和name字段,确保返回的结构完全符合你的期望,不会包含分类文档中的其他冗余字段。

额外优化建议

如果你的数据集比较大,这种逐个查询分类的方式会产生大量数据库请求,可能影响性能。可以考虑先收集所有需要查询的分类ID,一次性批量查询,再映射到对应的结果中:

// 收集所有需要查询的分类ID,去重避免重复查询
const allCategoryIds = [...new Set(searchResults.flatMap(item => item.categories))];
// 批量查询所有分类
const categoryMap = new Map(
  (await CategoryType.find({ _id: { $in: allCategoryIds } })).map(doc => [doc._id.toString(), { _id: doc._id, name: doc.name }])
);

// 映射结果
const resultArray = searchResults.map(item => ({
  ...item,
  categories: item.categories.map(id => categoryMap.get(id.toString()))
}));

这种方式只需要1次数据库查询,性能会好很多,尤其是在数据量较大的场景下。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 06:24:06