【问题标题】:Mongoose - How to save results to an arrayMongoose - 如何将结果保存到数组
【发布时间】:2018-04-07 09:47:56
【问题描述】:

我有一个 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) 放在数组之外(这是我想要的),它会打印一个空字符串。谁能解释这种行为并为此提出解决方案?谢谢。

【问题讨论】:

  • 你能解释一下“但是如果我把 console.log(dietaryResults) 放在数组之外”的意思吗?您是指在回调之外还是在嵌套的 for 循环之外?
  • 我的意思是在这个Restaurant.find(之外

标签: javascript arrays mongodb mongoose


【解决方案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】:

    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

    我建议一次搜索所有必需的数据,并避免在循环内搜索以进行单个回调,并在该回调内使用结果做你需要的一切。

    这样的事情可能会奏效。如果没有,您应该寻找某种方式在一个请求中获取所有数据

     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;
        });
    

    【讨论】:

    • 这段代码与 OP 有何不同?说明解决办法!这不是关于 NodeJS,而是关于 Mongoosejs。
    • @RandyCasburn 我的代码将有助于理解何时执行部分代码。作者将能够看到“循环结束”将在“添加”之前打印。所以,我正在解释行为,正如帖子中所要求的那样。
    • 我意识到这一点,但是当他们一开始不理解异步操作时,如果没有你解释你在为他们做什么,他们就不会知道这一点。我尽量避免对您的回答投反对票。请在回答中说明您的目的。
    • @ŞükranEken 告诉我怎么了)我认为我不应该在这里解释所有异步概念。我已经发布了它的链接。
    • @MichaelKapustey - 很好的答案!
    【解决方案3】:

    您需要回调或承诺。您可以在此之外使用 **Restaurant.find( ** 这个:setTimeOut(function s(){console.log(dietaryResults)},1000)

    因为你需要学习异步函数。

    【讨论】:

    • 我只是想打印出测试结果。实际上,我想将结果传递到其他地方,它仍然可以这样工作吗?
    【解决方案4】:

    截至javascript asynchronicity 时尚,您不能确定.exec 回调将在for 循环结束之前运行(并结束)。 (你可以通过阅读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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-30
      • 2021-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-26
      相关资源
      最近更新 更多