17

我有一个奇怪的问题让我感到困惑。我有一个模型:

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 事件,因此它正在保存。我也没有对变体结构进行任何检查——即没有只允许代码和价格的代码。我显然错过了一些东西,但几个小时后我的想法就用完了。

4

2 回答 2

33

当您修改无类型Array字段(如)的内容时variations,您需要通知 Mongoose 您已通过调用markModified(path)修改后的文档来更改其值,否则后续save()调用将不会保存它。请参阅文档

  for(var i = p.variations.length - 1; i >=0; i--) {
    p.variations[i]['color'] = 'red';
  }
  p.markModified('variations');
  p.save(function(err) { ...
于 2013-02-25T21:15:27.590 回答
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");
}

另一种方法是以旧方式更改字段的值,而无需通过设置器,然后手动将其标记为已修改:p.markModified('variations');

在我看来,您应该始终使用 setter,因为它更具可读性。您可以只传递一个包含所有参数更改的 json 对象,它会安全地更新您真正想要更改的字段。

于 2013-02-25T23:06:05.507 回答