2013-02-25 107 views
14

我有一個奇怪的問題,讓我感到困惑。我有一個模型:無法更新貓鼬模型

var Model = new Schema({ 
    name: String, 
    variations: Array 
}); 

變化入境看起來是這樣的:

[ {code: '', price: '' }, {code: '', price: '' }] 

我需要添加一個新的領域 - 說「色」。所以,我這樣做是爲了批量更新:

Model.find().exec(function(err, products) { 
    if (!err) { 
     products.forEach(function(p) { 
      for(var i = p.variations.length - 1; i >= 0; i--) { 
       p.variations[i]['color'] = 'red'; 
       // This shows all existing variations 
       // with the new color feed - correct 
       console.log(p.variations[i]); 
      } 
      p.save(function(err) { 
       if (!err) { 
        console.log("Success"); 
       } else { 
        console.log(err); 
       } 
      }); 
     });  
    } 
}); 

但「顏色」字段設置 - 如果我再重複一次,並註釋掉p.variations[i]['color'] = 'red';線則不會顯示。我似乎無法弄清楚爲什麼這樣做。我有一個正確觸發的onSave事件,所以它正在保存。我也沒有檢查變體結構 - 即沒有代碼只允許代碼和價格。我明顯錯過了一些東西,但幾個小時後,我用完了想法。

回答

26

當您修改非類型化Array字段的內容一樣variations,你需要通知你已經通過調用修改後的文檔或後續save()調用不會保存markModified(path)改變了它的價值貓鼬。 See docs

for(var i = p.variations.length - 1; i >=0; i--) { 
    p.variations[i]['color'] = 'red'; 
    } 
    p.markModified('variations'); 
    p.save(function(err) { ... 
+0

如果您使用鬆散類型模式的任何深度對象(mongoose.Schema.Types.Mixed),則也是如此。而從Mongoose 4.5.8開始,上述方法(markModified)仍然是一個可行的方法。 – SylonZero 2017-11-18 21:09:30

3

您必須使用set功能更改屬性。這背後的原因是貓鼬必須將該字段標記爲已修改以便保存到數據庫中。

for(var i = p.variations.length - 1; i >=0; i--) { 
    p.variations[i].set({"color":"red", "code":"herr"}); 
    // or 
    p.variations[i].set("color":"red"); 
    p.variations[i].set("code":"herr"); 
} 

另一種方法是改變字段的值是老樣子,沒有去trought二傳手,然後手動將其標記爲已修改:p.markModified('variations');

在我看來,你應該總是使用setter方法,因爲這是更具可讀性。你只需傳遞一個json對象,其中包含參數中的所有更改,它將安全地更新您想要更改的真實的字段。