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

Bur*_*rak 5 mongoose mongodb node.js 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);
Run Code Online (Sandbox Code Playgroud)

"name"字段是多语言的.我的意思是,我会保留多语言数据

name: {
    "en": "My Shop",
    "es": "Mi Tienda"
}
Run Code Online (Sandbox Code Playgroud)

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

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);
    });
};
Run Code Online (Sandbox Code Playgroud)

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

有没有办法做到这一点?

小智 13

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

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

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


Bla*_*ven 9

对特定元素使用"点表示法":

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

如果这是您想要做的事情,那么只会覆盖"en"元素,或者使用您设置的数据"创建"新元素.因此,如果您使用"de"并且不存在,那么将存在其他元素和具有该值的新"de".

  • @Burak你误会了,并没有阅读那里的最终声明.再读一遍.您要么更新现有内容,要么创建新的子元素.这一定是你需要在这里做的事情,因为我不可能想到你会期待的其他结果. (4认同)