Mongoose: Schema.pre('save') Not Working With Update Function

Created on 12 Feb 2015  路  8Comments  路  Source: Automattic/mongoose

I was testing with upsert option when I realize, upsert insert when called by Schema.update would not call schema.pre('save') middleware. Haven't done much test though.

How to reproduce:

Use update function with upsert option.

Schema.update(query, doc, {upsert: true}, function(){});

On respective schema model, use some plugin.

Schema.plugin(plugin.use);

Plugin pre('save') function wouldn't called.

exports.use= function (schema, options) {

  schema.pre('save', function (next) {
    console.log('this wouldn't show up');
    next();
  });
};

I don't know if this is a bug, or there's some flaw in my code. Currently not affecting much my code, but some explanation would be appreciated. Thanks. :)

Most helpful comment

pre('save') gets executed before a save() call. update() is not the same function as save(). However, 4.0.0-rc2 does have support for pre('update') hooks :)

All 8 comments

update does a regular mongo driver call. Schema.update bypass the middleware by design.

In the notes of the documentation to Model.update is defined what is not applyed.

  • defaults
  • setters
  • validators
  • middleware

If you want to get sure that your hooks are called, you have to get your model from DB (or hold it), edit it and use the save method on the model instance.

pre('save') gets executed before a save() call. update() is not the same function as save(). However, 4.0.0-rc2 does have support for pre('update') hooks :)

Oh, thanks for the clarification. I thought that because I use upsert function, It'll call save() method. Thanks. :)

This is misleading. pre('update') does not behave like pre('save') because the 'this' in the pre('update') is just the query and you cannot call useful functions like this.isNew or this.isModified() on it. pre('save') should be called either when creating or updating an object, because in either case one is "saving" the object.

Right now a lot of people are following this code for password hashing

https://stackoverflow.com/questions/14588032/mongoose-password-hashing

The assumption I (and I would be many others have) is that every time a user saves their user record this pre('save') is called.

Since we see here that this is not the case, if anyone changes their password, the password will not be salted and hashed.

I guess the work around is to always first call a find() then a save() and never use the update() functions at all. Seems like mongoose doesn't even need all the "update" style functions at all then since they are so dangerous and poorly documented.

@ajbraus what if we added an official plugin?

Sure @vkarpov15 - what does that entail? How do we get started? :D

@ajbraus Mongoose has some officially supported plugins. They're separate projects that have functionality that we want to support but not necessarily put into mongoose core. If you're interested in writing a plugin, you're more than welcome to give it a shot:

Plugins docs

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ChrisZieba picture ChrisZieba  路  76Comments

nparsons08 picture nparsons08  路  40Comments

joeytwiddle picture joeytwiddle  路  40Comments

wshaver picture wshaver  路  50Comments

ruimgoncalves picture ruimgoncalves  路  59Comments