Mongoose技术问询:如何将MongoDB查询结果保存至数组
搞定MongoDB异步查询结果存入数组的问题
嘿,我一眼就看出你遇到的是JavaScript异步操作顺序的坑!你现在的代码里,Restaurant.find().exec()是异步方法——循环会飞快地把所有查询都发出去,但每个查询的回调函数要等MongoDB返回数据才会执行。所以你如果在循环外面访问dietaryResults,大概率拿到的是空数组;而回调里的console.log也只能看到当前那一次查询的结果,不是所有查询都完成后的完整数组。
给你两个实用的解决方案,选哪个看你习惯:
方案1:用Promise.all批量处理异步查询
把每个查询转成Promise,然后等着所有查询都完成再合并结果,这样就能保证拿到完整的数组:
let dietaryResults = []; // 先把所有查询任务存成Promise数组 const queryTasks = []; for (const key in dietary) { // 不传回调的话,exec()会返回一个Promise const query = Restaurant.find( { $text: { $search: dietary[key] } }, { score: { $meta: "textScore" } } ) .sort({ score: { $meta: "textScore" } }) .exec(); queryTasks.push(query); } // 等待所有查询完成 Promise.all(queryTasks) .then(allQueryResults => { // 把所有结果合并到数组里 allQueryResults.forEach(results => { dietaryResults.push(...results); // 用扩展运算符一次性加完所有元素 }); console.log(dietaryResults); // 这里就是完整的结果啦 }) .catch(err => { console.error("查询出错啦:", err); });
方案2:用async/await写更清爽的代码
如果你的环境支持ES6+(现在大部分Node.js和浏览器都支持),用async/await会更直观,像写同步代码一样处理异步:
async function fetchDietaryResults() { let dietaryResults = []; for (const key in dietary) { // 用await等着当前查询做完再继续 const results = await Restaurant.find( { $text: { $search: dietary[key] } }, { score: { $meta: "textScore" } } ) .sort({ score: { $meta: "textScore" } }) .exec(); dietaryResults.push(...results); } console.log(dietaryResults); // 循环跑完就拿到完整数组了 return dietaryResults; } // 调用这个函数就行,记得处理错误 fetchDietaryResults().catch(err => console.error("查询出问题了:", err));
再唠唠原代码的问题根源
为啥原代码达不到预期?因为JS是异步非阻塞的:循环会快速遍历完所有dietary的key,把所有查询都发出去,但每个查询的回调要等MongoDB返回数据才会执行——这时候循环早就跑完了!如果你在循环外面写console.log(dietaryResults),那行代码会比所有回调都先执行,数组自然是空的。
用上面的方案就能完美解决这个异步顺序的问题,确保所有查询结果都被收集到数组里~
内容的提问来源于stack exchange,提问作者Tri Nguyen
相关产品推荐
相关产品推荐

