Using findOne in a loop takes too long in Node.js

后端 未结 5 484
时光取名叫无心
时光取名叫无心 2020-12-12 07:35

I\'m using Node.js with MongoDB, I\'m also using Monk for db access. I have the below code :

console.time(\"start\");

collection.findOne({name: \"jason\"},         


        
相关标签:
5条回答
  • 2020-12-12 08:09

    yes, it's because javascript's async nature. As you have called db from for loop javascript will not wait for it's response and continue the execution so it will print the file was saved first.

    about your ans 2 It's making a dbCall for every friend then it's obvious that it will take some time that's why it's taking 1 or 2 secs for every friend.

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

    This will make your async and db doubts more clear. As you will see it will print all console in line.

    InsideforLoop Calling 0 friend

    Terminating 0 -----

    and so on....Like this

    console.log(doc.name);

    but this will be printed asynchronusly

    Added

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

    Find All Details in one call

    0 讨论(0)
  • 2020-12-12 08:14

    Answer for question 1: Yes, you are right.

    Is it because the async nature of Node.js.

    And to prevent that Node.js provides some mechanism for that you can use it otherwise you can do it on your own manually by setting one flag.

    Answer for question 2:

    you can use $in instead of findOne, it will be ease and fast.

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

    arr :- In this you need to provide whole array.

    0 讨论(0)
  • 2020-12-12 08:26

    Answer to 1: Yes, it is because node is async. The part where it logs names is executed only when the first findOne returns, whereas the file was saved is executed straight away.

    0 讨论(0)
  • 2020-12-12 08:31
    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
                                        }    
                                    });
    
    0 讨论(0)
  • 2020-12-12 08:33
    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);
           }
    }
    }
    });
    
    0 讨论(0)
提交回复
热议问题