我有一个mongodb查询,我想将结果保存到数组中。我还在查询之外定义了一个空数组。
var dietaryResults = [];
for (var key in dietary){
Restaurant.find(
{ $text : { $search : dietary[key] } },
{ score : { $meta: "textScore" } }
).sort({ score : { $meta : 'textScore' } }).exec(function(err, results) {
for (var i in results){
dietaryResults.push(results[i]);
}
console.log(dietaryResults);
});
}
如果我在上面的查询中console.log(dietaryResults)
,我可以看到结果被推入数组。但是如果我把console.log(dietaryResults)
放在数组之外(这就是我想要的),它会打印一个空字符串。任何人都可以解释这种行为,并建议一个解决方案吗?感谢。
答案 0 :(得分:1)
Restaurant.find是异步的。
函数insinde .exec部分在循环结束后执行。
尝试
for (var key in dietary){
Restaurant.find(
{ $text : { $search : dietary[key] } },
{ score : { $meta: "textScore" } }
).sort({ score : { $meta : 'textScore' } }).exec(function(err, results) {
for (var i in results){
dietaryResults.push(results[i]);
}
console.log('added');
});
}
console.log('loop end');
你将能够看到,那个循环结束'在添加'之前将打印日志。登录。 如果你需要数组中的所有结果,你应该在回调中填充这个数组。没有办法同步获取数据。
有关回调和异步函数的详细信息,请查看以下文章:https://www.tutorialspoint.com/nodejs/nodejs_callbacks_concept.htm
我建议一次搜索所有必需的数据,并避免在内部循环中搜索单个回调,并在回调中执行所需的一切结果。
像这样的Smth可能会起作用。如果不是,您应该搜索某种方式来获取一个请求中的所有数据 Restaurant.find(
{ $text : { $search : { $in: Object.values(dietary)} } },
{ score : { $meta: "textScore" } }
).sort({ score : { $meta : 'textScore' } }).exec(function(err, results) {
for (var i in results){
dietaryResults.push(results[i]);
}
//do stuff here;
});
答案 1 :(得分:1)
当我使用bluebird
(这是一种Promise
)时,它可以正常工作。
var Promise = require('bluebird');
var mongoose = Promise.promisifyAll(require('mongoose'));
var promises = Restaurant.find({ $text : { $search : query } }, function(err, results) {
results.forEach(function(element) {
finalResults.push(element);
});
});
Promise.all(promises).then(function() {
console.log(finalResults);
}).error(console.error);
答案 2 :(得分:0)
你需要回调或承诺。你可以在这个**餐厅之外使用。(**
这样:setTimeOut(function s(){console.log(dietaryResults)},1000)
因为您需要学习异步功能。
答案 3 :(得分:0)
从javascript asynchronicity方式开始,您无法确定{for循环结束前.exec
回调是否会运行(并结束)。 (通过阅读event-loop)
这样,dietaryResults
在任何其他地方都可以为空(取决于查询速度)。
You can read more about using promises with mongoose and node in order to be sure dietaryResults
will be full with the results,
阅读Node event loop。
目前,我不完全确定这会奏效 - 但这是你的方向:
var query = {...} // (enter your query here)
var dietaryResults = [];
Object.entries(diatery).map(async key => {
const results = await Restaurant.find(query).sort();
results.map(result => dietaryResults.push(result));
});
console.log(dietaryResults);