2017-05-30 130 views
0

我正在使用mongodb和bigquery的nodejs。nodejs如何讓循環等待,直到運行循環的下一個實例

因爲它似乎bigquery只允許每個命令10k插入。

所以我做了主要查詢計數,並循環到從10K多少頁。

我得到500k與計數查詢,所以50頁或500循環。

如何讓循環等待直到運行循環的下一頁?

代碼:

var limit = 9999; 

mongo_client.connect(mongo_url, function(err, db) { 
    var query = {'_id.date_visited':{'$gte':'2016-01-01','$lt':'2016-02-01'}}; 

    db.collection('my_table').count(query,function(err, count){ 
     var pages = Math.ceil(count/limit); 

     console.log("count: "+count); 
     console.log("pages: "+pages); 

     for(var page=0;page<pages;page++){ 
      var skip = page * limit; 

      console.log("page: "+page); 
      console.log("skip: "+skip); 

      //HOW TO MAKE THIS loop wait till running next page of the loop 
      db.collection('my_table').find(query).sort({'_id.date_visited':1,'_id.hour_visited':1}).limit(limit).limit(skip).toArray(function(err, db_results) { 
       var documents = []; 
       async.each(db_results, function (db_resultsx, cb) { 
        documents.push(db_resultsx); 

        if(documents.length == db_results.length) { 
         //console.log(documents); 
         bigqueryClient 
          .dataset(dataset) 
          .table('my_table') 
          .insert(documents) 
          .then((insertErrors) => { 
          console.log('Inserted'); 
          //documents.forEach((row) => console.log(row)); 
          console.error(insertErrors); 
          if (insertErrors && insertErrors.length > 0) { 
           console.log('Insert errors:'); 
           insertErrors.forEach((err) => console.error(err)); 
          } 
          }) 
          .catch((err) => { 
          console.error('ERROR:'); 
          console.log(err); 
         }); 
        } 
       }); 
      }); 
     } 
    }); 
}); 
+0

那麼你已經在使用['async.each'](http://caolan.github.io/async/docs.html#each)了。看到這行'async.each(db_results,function(db_resultsx,cb){'''''''當你想要發信號通知循環的下一次迭代時,''cb''要小心,因爲你有'if'語句放在另一個異步方法之前,所以你應該在完成異步方法(bigQuery)以及需要與if匹配的else條件中調用該「回調」,否則我們不會發送信號 –

回答

1

我可能會取代與async.eachSeries循環,那麼你可以在循環的下一次迭代發生的決定,並自async.eachSeries只能同時運行1個操作,你會不會遇到同樣的錯誤

編輯:

通過讀碼後,我瘦k async.timesSeries(從我的評論中更正,async.timesSeries是正確的選項)是一個更好的選擇。這裏有一個例子:

async.timesSeries(pages, function(page, next) 
{ 
    var skip = page * limit; 
    // ... the rest of your code here 

    // when you want the next iteration to start, simply call: 
    next(); 
    /* 
    which will tell async that the current iteration is complete, 
    and it can do the next one. You can pass 2 parameters to next, 
    the first parameter is an error, and if error is not null it will 
    immediately call the function below, and the second parameter is an 
    item you can pass that will be added to an object which will be sent 
    as the second parameter in the function below 
    */ 
}, 
function(err, coll) 
{ 
    /* 
    this function will get called if there's an error 
    or when all iterations are completed 
    */ 
}); 

上面的代碼將取代你的for循環

+0

所以我需要餵給每個系列的頁面數以便循環/迭代多次? – Boy

+1

我稍微誤讀了這裏的意圖,並且在正確地查看代碼之後['async.times' ](https://caolan.github.io/async/docs.html#times)可能對你更有用,因爲它允許回調,所以你只需要在你想要的時候執行下一部分循環,而且它將運行'n'次 – Chifilly

+0

作爲內部默認值,它將等待直到l內部代碼完成直到下一個循環?還是我需要做別的事情?我是新的節點。 – Boy

2

我覺得一個for循環不會爲使用遞歸調用這樣的這種情況下,你可以循環一個很好的解決方案:

function performQuery(queryIndex) { 
    if(queryIndex >= limit) return; 

    db.exec('query', function(err, db_result) { 
     // your code 
     performQuery(queryIndex+1); 
    }) 
} 
performQuery(0); 
+0

我喜歡這個主意,但裏面的代碼,它的數據上傳至BigQuery,所以我想這要等到下次運行performQuery,或者我需要做performQuery的BigQuery的回調? – Boy

+1

如果你想等到bigquery結束,在bigquery回調中運行performQuery –

0

如果你不想使用遞歸的承諾,因爲你事先知道的項目數,你可以這樣來做:

// Create a "skip" array (there is certainly a nicer way to do it, with a modulo) 
var skips = []; 
for(var page=0;page<pages;page++){ 
    skips.push(page * limit); 
} 

// Put your mongoDB read and write code in a function 
// (that takes skip in entry and returns an array of documents) 
var myMongoDBFunc = function (skip) { 
    var documents = []; 

    db.collection('my_table') 
     .find(query) 
     .limit(limit) 
     .limit(skip) 
     .toArray(function(err, db_results) { 
      ... 
     }); 
    ... 
    return documents; 
} 

// And call it with async.concatSeries that will concatenate the results (documents) 
async.concatSeries(skips, myMongoDbFunc, function(err, documents) { 
    // Will be called at the end 
}); 

如果您想優化和並行運行所有查詢,只需將concatSeries替換爲concat(但順序無法保證)。

如果你不關心返回的文件(顯然你只想寫的東西),也許你可以使用async.seriesasync.parallel(由自己去查,我不知道特別async)。