如何在不覆盖当前数据的情况下更新Mongoose中的混合类型字段?

时间:2015-07-01 06:43:57

标签: node.js mongodb mongoose mongodb-query

我有以下架构

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ShopSchema = new Schema({
    name: Schema.Types.Mixed,
    country: {
        type: String,
        default: ''
    },
    createdAt: {
        type: Date,
        default: Date.now
    },
    defaultLanguage: {
        type: String
    },
    account: {type : Schema.ObjectId, ref : 'Account'},
});
mongoose.model('Shop', ShopSchema);

"名称"字段是多语言的。我的意思是,我将保留多语言数据,如

name: {
    "en": "My Shop",
    "es": "Mi Tienda"
}

我的问题是,在控制器中,我使用此代码来更新商店:

var mongoose = require('mongoose')
var Shop = mongoose.model('Shop')

exports.update = function(req, res) {

Shop.findByIdAndUpdate(req.params.shopid, {
    $set: {
        name: req.body.name
    }
}, function(err, shop) {
    if (err) return res.json(err);
        res.json(shop);
    });
};

很明显,新数据会覆盖旧数据。我需要的是用新的数据扩展旧数据。

有没有办法做到这一点?

2 个答案:

答案 0 :(得分:11)

您应该使用方法 .markModified()。请参阅文档http://mongoosejs.com/docs/schematypes.html#mixed

  

由于它是无模式类型,您可以将值更改为您喜欢的任何其他值,但Mongoose无法自动检测并保存这些更改。要“告诉”Mongoose混合类型的值已更改,请调用文档的.markModified(path)方法,将路径传递给刚刚更改的混合类型。

person.anything = { x: [3, 4, { y: "changed" }] };
person.markModified('anything');
person.save(); // anything will now get saved

答案 1 :(得分:9)

使用"dot notation"作为特定元素:

Shop.findByIdAndUpdate(req.params.shopid, {
    "$set": {
        "name.en": req.body.name
    }
}, function(err, shop) {
    if (err) return res.json(err);
        res.json(shop);
    });
});

这只会覆盖" en"元素,如果这是你想要做的或"创建"包含您设置的数据的新元素。所以,如果你使用" de"并且不存在将会有其他元素和新的" de"一个有价值的。