2012-03-16 65 views
2

的NodeJS +快遞,MongoDB的+貓鼬的NodeJS:保存功能在for循環,異步麻煩

我有一個JSON提要其中每個記錄都有一套「場地」屬性,如「地名」,「場地位置(事「」場地電話「等)。我想創建一個飼料中所有場地的集合 - 每個場地的一個實例,沒有模糊。

我循環瀏覽JSON並測試會場中是否存在會場。如果沒有,請保存。

jsonObj.events.forEach(function(element, index, array){ 
    Venue.findOne({'name': element.vname}, function(err,doc){ 
     if(doc == null){ 
      var instance = new Venue(); 
      instance.name = element.vname; 
      instance.location = element.location; 
      instance.phone = element.vphone; 
      instance.save(); 
     } 
    } 
} 

期望的:所有場地的列表(沒有模糊)。

結果:在場館收集中有大量的投資。

基本上,循環爲JSON提要中的每個記錄創建了一個新的Venue記錄。

我正在學習Node及其異步特性,所以我相信即使在第一個save()函數完成之前for循環也會完成 - 所以if語句總是檢查一個空集合。 Console.logging支持此聲明。

我不知道如何重做這個,以便它執行所需的任務。我嘗試過caolan的異步模塊,但我無法獲得幫助。我錯誤地使用了一個很好的機會。

非常感謝你指點我在正確的方向 - 我已經無濟於事。如果異步模塊是正確的答案,我很樂意幫助你解決這個問題。

再次感謝!

回答

2

爲什麼不用另一種方式呢?你沒有說明你的持久層是什麼,但它看起來像貓鼬或可能FastLegS。無論哪種情況,您都可以在名稱字段上創建唯一索引。然後,您可以嘗試保存任何內容,並在出現唯一索引違規時處理該錯誤。

+0

啊哈!是的,它做到了。我正在使用Mongoose並忽略了設置唯一索引。謝謝保羅! – Ghan 2012-03-16 03:36:29

1

不管你做什麼,你必須按照@Paul的建議,在數據庫中建立一個唯一的索引。這是確保唯一性的唯一途徑。

但是,你的代碼的主要問題是在instance.save()調用中,你需要一個觸發下一次迭代的回調,否則數據庫將沒有時間來保存新記錄。這是一個競賽條件。你可以用caolan的forEachSeries函數來解決這個問題。

或者,您可以在Venue集合中獲得與JSON對象中的項目匹配的記錄數組,然後將匹配過濾出對象,然後迭代添加已過濾JSON對象中剩下的每個項目。這將通過不首先創建重複數據庫來最大限度地減少數據庫操作的數量。

Venue.find({'name': { $in: jsonObj.events.map(function(event){ return event.vname; }) }}, function (err, docs){ 
    var existingVnames = docs.map(function(doc){ return doc.name; }); 
    var filteredEvents = jsonObj.events.filter(function(event){ 
    return existingVnames.indexOf(event.vname) === -1; 
    }); 
    filteredEvents.forEach(function(event){ 
    var venue = new Venue(); 
    venue.name = event.vname; 
    venue.location = event.location; 
    venue.phone = event.vphone; 
    venue.save(function (err){ 
     // Optionally, do some logging here, perhaps. 
     if (err) return console.error('Something went wrong!'); 
     else return console.log('Successfully created new venue %s', venue.name); 
    }); 
    }); 
});