Do you want to request a feature or report a bug?
What is the current behavior?
If the current behavior is a bug, please provide the steps to reproduce.
What is the expected behavior?
Please mention your node.js, mongoose and MongoDB version.
You could always use a setter to return the value to prevent anyone from setting a new value on it if the field already exists.
const schema = new mongoose.Schema({
theField: {
type: String,
set: function(v) {
if (this.theField) {
return this.theField;
} else {
return v;
}
}
}
});
Another option is to always access the value via a virtual without a setter
But I tried you example and find the program can not run into this set function @varunjayaraman
@Prumeth-shen What exactly does not work / what does happen? (So we can help you more precisely.)
For now: setters are executed when Mongoose tries to save a document to the database their respective property gets reassigned, hope that helps. Here are the docs for more info: http://mongoosejs.com/docs/api.html#schematype_SchemaType-set.
@c0d0g3n Perhaps I am not described exactly,what I want to do is that when there exist a document, it has a field , for example, named type, then I want to update this document using a new type value, and this behavior have to be forbidden, because I want type's value to be not modified, I think setters are not executed in this case, because what I want to do is based on a document that already exist in mongoDB. Thanks for you answer.
@Prumeth-shen I've quickly created a stand-alone script to show how setters work: https://gist.github.com/c0d0g3n/c7f382bb858ac2fa797f4edd4097b40b. I hope the code can speak for itself. As you can see the setters do get executed when you try to assign a value to the respective property. This means you can use a set function to discard the submitted value and return the value that's already in the database, thus making the respective property 'unmodifiable'. (Note that I was wrong about setters being called on save in my previous comment.)
I hope this solves your problem :)
@c0d0g3n I know what you said, and I have searched for something like this: https://github.com/Automattic/mongoose/issues/3970 , it tells us that by design, findOneAndUpdate() is very different from save(), what you code doing is based on save(), while I am using findOneAndUpdate(), so I think that is why I can not find the program run into this setters, so I tried to use pre('findOneAndUpdate') hook and it worked, but I think this is not efficient,because in the pre('findOneAndUpdate') hook I must add a MongoDB find().
@Prumeth-shen Setters are indeed not executed for .findOneAndUpdate()
and the likes as the documentation says.
I don't think you need to do an additional query because the current document is available under this
in hooks:
testSchema.pre('validate', function (next) {
console.log(this) // current document
next()
})
Note using an es6 arrow function here doesn't work, as they handle this
slightly different.
Also, please publish some sample code or a richer description of your issue next time, so we can help you more specific from the meet on.
Have a good time! :)
You can also check in a pre('findOneAndUpdate')
hook whether that field is getting modified. 4.10 will also have the ability to run setters on update, follow #4132 for updates.
I had the same problem with field modifications.
Try https://www.npmjs.com/package/mongoose-immutable-plugin
The plugin will reject each modification-attempt on a field and it works for
Update
UpdateOne
FindOneAndUpdate
UpdateMany
Re-save
It supports immutability on array, object, etc. type of field and guards deep immutability.
Plugin also handles update-options as $set, $inc, etc.
Most helpful comment
You could always use a setter to return the value to prevent anyone from setting a new value on it if the field already exists.
Another option is to always access the value via a virtual without a setter