在Node.js中使用循环中的findOne需要太长时间

时间:2017-07-19 11:46:27

标签: javascript node.js mongodb

我在MongoDB中使用Node.js,我也使用Monk进行数据库访问。我有以下代码:

console.time("start");

collection.findOne({name: "jason"},
function(err, document) {

  for(var i = 0; i < document.friends.length; i++) // "friends is an array contains ids of the user's friends"
  {
    collection.findOne({id: document.friends[i]}, function(err, doc)
    {
      console.log(doc.name);
    });
   }

});

console.log("The file was saved!");
console.timeEnd("start");

我对此代码有两个问题:

  1. 我看到执行时间和“文件已保存!”首先是字符串,然后我看到控制台中的朋友的名字。这是为什么?我不应该先看到名字然后是执行时间吗?是因为Node.js的异步特性吗?
  2. 名称在控制台中打印速度非常慢,速度就像两秒钟内的名字一样。为什么这么慢?有没有办法让这个过程更快?
  3. 编辑:

    将朋友列表分成小块并异步调用朋友是不是一个好主意?它会使这个过程更快吗?

    编辑2:

    我将代码更改为:

    collection.find({ id: { "$in": document.friends}}).then(function(err, doc)
    {
      console.log(doc.name);
    
          if(err) {
          return console.log(err);
           }
    }
    

    这不会出错,但这也不会打印任何内容。

    提前致谢。

5 个答案:

答案 0 :(得分:4)

回答问题1: 是的,你是对的。

是因为Node.js的异步特性。

为了防止Node.js提供某些机制,你可以使用它,否则你可以通过设置一个标志手动自己完成。

回答问题2:

您可以使用$in代替findOne,它会轻松快捷。

e.g。 .find({ "fieldx": { "$in": arr } })

arr: - 在此你需要提供整个数组。

答案 1 :(得分:2)

是的,这是因为javascript的异步性质。 正如你从for循环调用db javascript将不会等待它的响应并继续执行所以它将打印文件先保存。

关于你的问题2 它正在为每个朋友制作一个dbCall,然后显然需要一些时间,这就是为什么每个朋友需要1或2秒的时间。

console.time("start");

collection.findOne({name: "jason"},
function(err, document) {

  for(var i = 0; i < document.friends.length; i++) // "friends is an array contains ids of the user's friends"
  {
    console.log("InsideforLoop Calling " + i + " friend");
    collection.findOne({id: document.friends[i]}, function(err, doc)
    {
      console.log(doc.name);
    });
    console.log("Terminating " + i + "-----");
   }

});

console.log("The file was saved!");
console.timeEnd("start");

这将使您的异步和数据库疑问更加清晰。 正如您将看到的那样,它将打印所有控制台。

  

InsideforLoop致电0朋友

     

终止0 -----

依此类推......就像这样

  

的console.log(doc.name);

     

但这将以异步方式打印

<强>加

collection.findOne({name: "jason"},
function(err, document) {

      //you can do this
      collection.find({id: $in:{document.friends}, function(err, doc)
        {
          console.log(doc);
        });

});
  

在一个电话中查找所有详细信息

答案 2 :(得分:1)

collection.findOne({name: "jason"},
function(err, document) {

if(document != undefined){
    collection.find({ id: { "$in": document.friends}}).then(function(err, doc)
{
  console.log(doc.name);

      if(err) {
      return console.log(err);
       }
}
}
});

答案 3 :(得分:1)

collection.aggregate([
                                {
                                    $match:{
                                        id :{ "$in" : document.friends},
                                    }
                                }
                                ]).exec(function ( e, d ) {
                                    console.log( d )            

                                    if(!e){
                                        // your code when got data successfully
                                    }else{
                                        // your code when you got the error
                                    }    
                                });

答案 4 :(得分:0)

答案1:是的,这是因为节点是异步的。它记录名称的部分仅在第一个findOne返回时执行,而the file was saved立即执行。