2017-08-29 45 views
0

我只是習慣於承諾,我想添加一個額外的ObjectId引用到表。我使用此代碼:如何立即執行貓鼬查詢並用Promise.all等待它們?

'use strict'; 

const mongoose = require('mongoose'); 
const config = require('config'); 

mongoose.connect(config.get("DBUrl"), {useMongoClient: true}); 
mongoose.set('debug', true); 

require('../model/AnnotationRequest'); 
require('../model/Website'); 

const AnnotationRequest = mongoose.model('AnnotationRequest'); 
const Website = mongoose.model('Website'); 

foo(function() { 
    console.log('done'); 
}); 

function foo(done) { 

    Website.find() 
     .then(function (websites) { 
      if (!websites) console.error('could not find any websites'); 

      AnnotationRequest.find({website: {$exists: false}}) 
       .then(function (annotationRequests) { 

        let jobs = []; 

        for (let k = 0; k < annotationRequests.length; k++) { 
         let found = false; 

         for (let i = 0; i < websites.length; i++) { 
          let websiteAnnotations = websites[i].annotations; 

          for (let o = 0; o < websiteAnnotations.length; o++) { 

           if (websiteAnnotations[o].equals(annotationRequests[k].annotation)) { 
            found = true; 
            annotationRequests[k].website = websites[i]; 
            jobs.push(
             annotationRequests[k].save() 
              .then(function (res) { 
               console.log("success saving", res._id); 
              }).catch(function (err) { 
               console.error(err); 
               done(err); 
              }) 
            ); 
            break; 
           } 
          } 
          if (found) { 
           break; 
          } 
         } 
        } 

        Promise.all(jobs).then(
         function() { 
          done(); 
         } 
        ).catch(function (err) { 
         console.error(err); 
        }); 
       }); 
     }); 
} 

第一個保存查詢被報告在Promise.all語句中啓動。是否在第一個.save()聲明後不立即執行查詢?我怎樣才能立即啓動它們?

另一個問題是,對於200k條目,此代碼需要2個小時。在服務器上,我們有> 2M條目。不知道它是否會起作用。有什麼建議麼?

感謝

+0

要執行大量插入我可以強烈建議你看看批量操作(https://docs.mongodb.com/manual/reference/method/Bulk/)。 –

回答

2

節點運行單線程,所以如果你有20萬個循環中的所有語句保存等待,直到你的代碼同步執行和完成。

嘗試使用異步模塊使您的代碼更加異步友好。 https://caolan.github.io/async/

嘗試此代碼,但此代碼與您的代碼有相同的錯誤。如果有多個網站有同樣的註釋,您的設置先找到了,我的可能最後找到了。

'use strict'; 

const mongoose = require('mongoose'); 
const config = require('config'); 
const async = require('async'); 


mongoose.connect(config.get("DBUrl"), {useMongoClient: true}); 
mongoose.set('debug', true); 

require('../model/AnnotationRequest'); 
require('../model/Website'); 

const AnnotationRequest = mongoose.model('AnnotationRequest'); 
const Website = mongoose.model('Website'); 

foo(function() { 
    console.log('done'); 
}); 

function foo(done) { 

    const pageSize= 10000; 

    async.parallel([function(callback) { 

     Website.find().then(function(websites) { 
      callback(null, websites); 
     }).catch(callback); 

    },function(callback) { 
     AnnotationRequest.count({website: {$exists: false}}).then(function(count) { 
      callback(null, count); 
     }).catch(callback); 
    }], function(err, results) { 

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

     const websites = results[0]; 
     const annotationRequestsCount = results[1]; 

     let websiteAnnotationMap = {}; 

     websites.forEach(function (website) { 
      website.annotations.forEach(function (annotation) { 
       websiteAnnotationMap[annotation] = website; 
      }); 
     }); 


     var skip = 0; 

     async.during(
      function (callback) { 
       return callback(null, skip < annotationRequestsCount); 
      }, 
      function (callback) { 

       AnnotationRequest.find({website: {$exists: false}}, { skip: skip, limit: pageSize }) 
        .then(function(annotationRequests) { 

         skip += pageSize; 

         async.each(annotationRequests, function(annotationRequest, eachCallback) { 

          let website = websiteAnnotationMap[annotationRequest.annotation]; 
          if(website) { 
           annotationRequest.website = website; 
           annotationRequest.save().then(function() { 
            eachCallback(); 
           }).catch(eachCallback); 

          } else { 
           eachCallback(); 
          } 
         }, callback); 
       }).catch(callback); 
      }, 
      done 
     ); 


    }); 
} 
+0

謝謝。這個按預期工作 – LandoR

+0

剛試過產品數據庫:'致命錯誤:CALL_AND_RETRY_LAST分配失敗 - JavaScript堆內存不足' – LandoR

+0

你提到了2M記錄,所以你需要實現一些分頁。 – reawer