如何提交编号数组查询MongoDB集合,单次请求返回目标文档对象数组?
问题分析
原代码的核心问题是异步map不会等待内部的Promise完成,purchases.map(async ...)会立刻返回一个Promise数组,但代码没有等待这些Promise执行完毕就直接返回了响应,导致返回的purchases还是初始的编号数组,而非查询后的文档对象。另外,直接修改原数组的做法也不够规范。
解决方案
方案1:用Promise.all处理异步查询(兼容原有逻辑)
把map返回的Promise数组用Promise.all包裹,等待所有查询完成后再生成新数组:
const Purchase = require('../models/purchase.model') //Get user purchases const getPurchases = async(req, res) => { const purchaseNos = req.body.purchases; if (!purchaseNos || purchaseNos.length === 0) { return res.json({ status: 'error', purchase: false }) } // 用map生成查询Promise数组,再用Promise.all等待全部完成 const purchases = await Promise.all( purchaseNos.map(async (transNo) => { const purchase = await Purchase.findOne({ trans_no: transNo }); if (!purchase) { // 处理不存在的编号,可根据需求返回默认值或跳过 return null; } return { date: purchase.date, total: purchase.total, merchant_name: purchase.merchant_name, merchant_id: purchase.merchant_id, mop: purchase.mop, items: purchase.items, trans_no: purchase.trans_no }; }) ); // 过滤掉null的结果(如果有的话) const validPurchases = purchases.filter(item => item !== null); return res.json({ status: 'ok', purchases: validPurchases }); } module.exports = { getPurchases }
方案2:用MongoDB的$in操作符单次查询(推荐,效率更高)
直接通过$in条件一次查询所有匹配的文档,避免多次数据库请求,完全符合“单次请求完成”的需求:
const Purchase = require('../models/purchase.model') //Get user purchases const getPurchases = async(req, res) => { const purchaseNos = req.body.purchases; if (!purchaseNos || purchaseNos.length === 0) { return res.json({ status: 'error', purchase: false }) } // 单次查询所有匹配trans_no的文档 const purchases = await Purchase.find({ trans_no: { $in: purchaseNos } }).select('date total merchant_name merchant_id mop items trans_no'); // 如果需要保持原数组的顺序(因为find返回的顺序不一定和$in数组一致),可以重新排序 const orderedPurchases = purchaseNos.map(no => purchases.find(p => p.trans_no === no) ).filter(item => item !== undefined); return res.json({ status: 'ok', purchases: orderedPurchases }); } module.exports = { getPurchases }
说明:
$in操作符会匹配trans_no在purchaseNos数组中的所有文档,一次请求完成查询,比多次findOne效率高得多。select方法用来指定返回的字段,和你手动构造purchaseObj的效果一致,更简洁。- 额外做了顺序保持:因为MongoDB返回的文档顺序不一定和
$in数组的顺序一致,所以通过原数组重新映射排序,确保结果顺序和输入的编号顺序一致。
内容的提问来源于stack exchange,提问作者GT Thompson
相关产品推荐
相关产品推荐

