无法更新mongoose模型

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);
                }
            });
        });     
    }
});

然而,“color”字段未设置——如果我再次通过并注释掉p.variations[i]['color'] = 'red';这一行,那么它就不会显示。我似乎无法弄清楚为什么会这样。我有一个正确触发保存的onSave事件。我还没有对变量结构进行任何检查——即没有只允许代码和价格的代码。显然我错过了什么,但几个小时后我已经没有想法了。
2个回答

33
当您修改未定义类型的Array字段(如variations)的内容时,需要调用markModified(path)通知Mongoose您已更改其值,否则后续的save()调用将不会保存它。请参阅文档
  for(var i = p.variations.length - 1; i >=0; i--) {
    p.variations[i]['color'] = 'red';
  }
  p.markModified('variations');
  p.save(function(err) { ...

如果您使用带有松散类型模式(mongoose.Schema.Types.Mixed)的深层对象,上述方法(markModified)仍然是Mongoose 4.5.8的有效方法。 - SylonZero

3
你需要使用set函数来更改属性。这样做的原理是为了让mongoose将该字段标记为已修改,以便保存到数据库中。
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");
}

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

在我看来,您应该始终使用setter,因为这样更易读。您只需传递一个包含所有更改的json对象即可安全地更新您真正想要更改的字段。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接