Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update mixed type field in Mongoose without overwriting the current data?

I have the following schema

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" field is multilingual. I mean, I will keep the multilingual data like

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

My problem is, in a controller, I am using this code to update the shop:

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

and it is obvious that new data overrides the old data. What I need is to extend the old data with the new one.

Is there any method to do that?

like image 754
Burak Avatar asked Jul 01 '15 06:07

Burak


People also ask

Which update method is valid if we want to update single document in Mongoose model?

Mongoose | update() Function The update() function is used to update one document in the database without returning it.

Can we overwrite Mongoose default ID with own id?

You can also overwrite Mongoose's default _id with your own _id . Just be careful: Mongoose will refuse to save a document that doesn't have an _id , so you're responsible for setting _id if you define your own _id path.

What is Upsert true in Mongoose?

The upsert = true option creates the object if it doesn't exist. defaults to false.

What is the __ V field in Mongoose?

In Mongoose the “_v” field is the versionKey is a property set on each document when first created by Mongoose. This is a document inserted through the mongo shell in a collection and this key-value contains the internal revision of the document.24-Jun-2021.


2 Answers

You should to use the method .markModified(). See the doc http://mongoosejs.com/docs/schematypes.html#mixed

Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect and save those changes. To "tell" Mongoose that the value of a Mixed type has changed, call the .markModified(path) method of the document passing the path to the Mixed type you just changed.

person.anything = { x: [3, 4, { y: "changed" }] };
person.markModified('anything');
person.save(); // anything will now get saved
like image 105
Julio Silveira Melo Avatar answered Sep 28 '22 23:09

Julio Silveira Melo


Use "dot notation" for the specific element:

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

That wil either only overwrite the "en" element if that is what you want to do or "create" a new element with the data you set it to. So if you used "de" and that did not exist there will be the other elements and a new "de" one with the value.

like image 38
Blakes Seven Avatar answered Sep 29 '22 01:09

Blakes Seven