Mongoose: schema.pre('save') not triggered by MyModel.update()

Created on 16 Jul 2011  ·  11Comments  ·  Source: Automattic/mongoose

example.js:

var mongoose = require('mongoose')
  , Schema = mongoose.Schema

mongoose.connect('mongodb://localhost/test')

var Thing = new Schema({
  title : String,
  content : String
})

Thing.pre('save', function(next){
  console.log("saving: %s (%s)", this.title, this.content)
  next()
})

var MyThing = mongoose.model('Thing', Thing)

var example = new MyThing({
  title : 'foo',
  content : 'bar'
})

example.save(function(err){
  MyThing.update({title:'foo'},{content:'baz'}, function(err, rs){
    console.log(rs)
  })  
})

Output:

$ node example.js 
saving: foo (bar)
1

The pre is triggered by the initial save, but not the update.

Most helpful comment

This is not a bug. pre save is a hook that fires on instances when their save method is called, not on the model when update is called.

Model.update let's you send atomic $set operations directly to mongodb.

All 11 comments

This is not a bug. pre save is a hook that fires on instances when their save method is called, not on the model when update is called.

Model.update let's you send atomic $set operations directly to mongodb.

This is a feature I'd like to have; especially helpful when upserting sparse data.

@aheckman I agree with @martindale, I feel that in UI's where we have $.ajax form updates such as by passing a req.body._id to a post route, some type of pre method would be handy. An example use case is when you submit two numbers, and you'd like the model to have a pre('save') for calculating the total.

perhaps pre('update') ofc

I have noticed this as well so I assume this is not considered an enhancement worth adding.

I decided to use aheckmann's approach where I need to update my object's updatedOn date field. However, where auditing is something I'd like to use at the middleware level, this approach smells.

Setting a date in my case is very sensitive to the instant the save commits to mongodb since I have a background process loading updated docs based on a moving date & time window. I'm not saying there would be a lot of time drift but aheckmann's approach vs. pre('update') would likely contain more drift by the time the save happens.

I would love to see some middleware option here.

So what is the workaround? I expected pre('save') would have caught updates, which semantically seem like saves to me. Since updates are so common, it makes the save hook much less valuable.

I am not sure if anyone is still watching this or not, but looking into the Mongoose documentations -
Mongoose
under _Notes on findAndUpdate()_ section makes a reference to issues/964 which explains why this does not work. Hope that helps! :)

This is fucking bullshit. we can't do anything async in setters. idiots.

this is a really old thread but ok. There are pre's that actually inturup this or it has been figured out since the post.

It's all good trent, i went ahead and reorganized my code to make a findById and then a subsequent save, so the pre save hook to salt a password still works. I guess it is what it is, though it would be nice to have a pre update hook as well, it still will take two queries to service the operation since you must read data and check if it has changed any way with isModifed

Tagging #964 and bumping for interest.

Was this page helpful?
0 / 5 - 0 ratings