如何获取Mongoose Cursor流文档总数?解决批量发送剩余数据问题
解决Mongoose Cursor遍历剩余文档未发送及获取总数问题
你遇到的核心问题有两个:一是遍历结束后剩余不足50条的文档没被发送到API,二是想获取当前cursor对应的总文档数量。下面给你针对性的解决方案:
一、修复剩余文档未发送的问题
你的现有代码只在每积累50条时发送一次,但遍历结束后如果res里还有剩下的文档(比如总共有53条,最后3条就会留在数组里),就会被遗漏。我们只需要在eachAsync执行完成后,额外检查并发送剩余内容即可:
async function exportQuotes(from, to) { let i = 0; // 调整初始值,让计数逻辑更直观 let res = []; const quotes = findQuotes(from, to); // 遍历cursor中的每一条文档 await quotes.eachAsync(async (doc) => { res.push(quoteMapper(doc)); i += 1; // 每积累50条就发送一次 if (i === 50) { await sendQuotesTest(res); // 重置计数器和数组 i = 0; res = []; } }); // 遍历结束后,发送剩下的不足50条的文档 if (res.length > 0) { await sendQuotesTest(res); } return Promise.resolve(); // 可根据需求返回统计结果或其他数据 }
二、获取Cursor对应的文档总数
Mongoose的cursor本身不会直接返回总条数,我们需要单独执行一个和findQuotes过滤条件完全一致的计数查询:
// 单独封装计数函数,确保过滤条件和findQuotes保持同步 async function getQuotesTotalCount(from, to) { return Draft.countDocuments({ lastPriceRequest: { $ne: null }, updatedAt: { $gte: from.toISOString(), $lte: to.toISOString(), }, }); }
然后在exportQuotes中调用这个函数,就能拿到总条数了:
async function exportQuotes(from, to) { // 先获取总文档数 const totalCount = await getQuotesTotalCount(from, to); console.log(`本次需要处理的文档总数:${totalCount}`); let i = 0; let res = []; const quotes = findQuotes(from, to); await quotes.eachAsync(async (doc) => { res.push(quoteMapper(doc)); i += 1; if (i === 50) { await sendQuotesTest(res); i = 0; res = []; } }); if (res.length > 0) { await sendQuotesTest(res); } // 可以返回处理统计信息 return { totalCount, processedCount: totalCount // 这里假设所有文档都成功处理,实际可根据情况调整 }; }
关于计数的小提示
countDocuments会精确统计符合过滤条件的文档数量,但对于超大数据集可能会有轻微性能开销。- 如果不需要精确计数,也可以用
estimatedDocumentCount,但它会忽略过滤条件,只返回集合的大致文档总数,所以不适合你的场景。
额外优化建议
- 给
sendQuotesTest添加错误处理逻辑,比如捕获请求失败的异常,记录日志或进行重试,避免因为单次API调用失败导致整个流程中断。 - 因为
eachAsync默认是串行执行的,所以不用担心并发发送API请求的问题;如果需要提高效率,可以考虑设置parallel参数,但要注意API的并发限制。
内容的提问来源于stack exchange,提问作者Flo4555
相关产品推荐
相关产品推荐

