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

Node.js中async/await结合for循环问题:未获取noOfContracts字段

问题解决:async/await循环中添加的noOfContracts字段未返回

核心原因

你通过Contact.find()获取的cons是Mongoose文档实例数组,而非普通JavaScript对象。Mongoose会严格按照定义的Schema字段进行序列化,直接给文档实例添加额外字段(如noOfContracts)不会被自动包含在返回的JSON结果中。

解决方案

方案1:查询时直接返回普通对象(推荐)

在Contact.find()中添加lean()选项,直接获取普通JS对象,后续添加字段无需额外转换:

// 原查询改为带lean(),直接返回普通对象
const cons = await Contact.find(where).lean();
const cons2 = await countContracts(cons);
res.send(cons2);

async function countContracts(cons) {
  for (let i = 0; i < cons.length; i++) {
    cons[i].noOfContracts = await Contract.countDocuments({
      contactId: cons[i]._id,
    });
  }
  return cons;
}

方案2:将Mongoose文档转换为普通对象

如果无法修改查询语句,可先把文档实例转成普通对象再添加字段:

async function countContracts(cons) {
  // 转换为普通JS对象数组
  const plainContacts = cons.map(doc => doc.toObject());
  for (let i = 0; i < plainContacts.length; i++) {
    plainContacts[i].noOfContracts = await Contract.countDocuments({
      contactId: plainContacts[i]._id,
    });
  }
  return plainContacts;
}

方案3:用Mongoose的set方法添加字段

若需保留Mongoose文档的其他功能,可通过set方法添加字段,最后转换为对象返回:

async function countContracts(cons) {
  for (let i = 0; i < cons.length; i++) {
    // 使用set方法给文档添加字段
    cons[i].set('noOfContracts', await Contract.countDocuments({
      contactId: cons[i]._id,
    }));
  }
  // 转换为普通对象数组后返回
  return cons.map(doc => doc.toObject());
}

性能优化:并行处理请求

你的原代码是串行执行每个计数查询,效率较低。可改用Promise.all并行发起所有请求,大幅缩短处理时间:

async function countContracts(cons) {
  const plainContacts = cons.map(doc => doc.toObject());
  // 并行处理所有计数请求
  await Promise.all(plainContacts.map(async contact => {
    contact.noOfContracts = await Contract.countDocuments({
      contactId: contact._id,
    });
  }));
  return plainContacts;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:35:27