Mongoose: Does mongoose suport a configuration in schema to let one field's value to be not modefied

Created on 27 Apr 2017  ·  9Comments  ·  Source: Automattic/mongoose

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.

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.

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

All 9 comments

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.

Was this page helpful?
0 / 5 - 0 ratings