Reputation: 222369
How can document count for particular model be acquired in both save
and update
Mongoose pre hooks/middlewares?
Considering that this
is query in update
hook, this works well:
schema.pre('update', function (next) {
this.model.count().then...
});
But in save
hook this
schema.pre('save', function (next) {
this.count().then...
});
results in
this.count is not a function
When debugging callbacks, this
in save
hook and this.model
in update
hook appear to be 'models' (instances of Model
). What's the difference between them?
Why does model instance in save
hook miss count
method? How can these two callbacks be unified to get document count?
I would prefer to stick to this
and not hard-code a model, because this allows to use ES6 classes conveniently for schema inheritance.
Upvotes: 3
Views: 6450
Reputation: 16805
Actually this.model
will not work for (pre save hook/middlewares) pre.('save'
but this.model
will work for pre hook of update
, findOneAndUpdate
.. etc
for pre.('save'
hook you need to use this.constructor
instead of this.model
like : this.constructor.count
or this.constructor.findOne
etc.
In my example assume create Schema for Country
so you can use like bellow :
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var CountrySchema = new Schema({
name: String,
//....
});
CountrySchema.pre('save', function(next) {
var self = this;
self.constructor.count(function(err, data) {
if(err){
return next(err);
}
// if no error do something as you need and return callback next() without error
console.log('pre save count==', data);
return next();
});
});
CountrySchema.pre('update', function (next) {
var self = this;
self.model.count(function(err, data) {
if(err){
return next(err);
}
// if no error do something as you need and return callback next() without error
console.log('pre update count===', data);
return next();
});
});
module.exports = mongoose.model('Country', CountrySchema);
OR
Can use mongoose.models['modelName']
like: mongoose.models['Country'].count()
for example
CountrySchema.pre('save', function(next) {
mongoose.models['Country'].count(function(err, data) {
if(err){
return next(err);
}
console.log('pre save count==', data);
return next();
});
});
CountrySchema.pre('update', function (next) {
mongoose.models['Country'].count(function(err, data) {
if(err){
return next(err);
}
console.log('pre update count===', data);
return next();
});
});
N.B: Why this.model
not working in pre hook of save
?
Middleware (also called pre and post hooks) are functions which are passed control during execution of asynchronous functions.
In Mongoose has 2 types of middleware:
- Document middleware and
- Query middleware
Document middleware is supported for functions.
init
, validate
, save
, remove
Query middleware is supported for functions.
count
, find
, findOne
, findOneAndRemove
, findOneAndUpdate
, insertMany
,update
In Mongoose Query middleware this.model
is the instance of your model that generated/defined by Mongoose. in this middleware this
return all instance variable that defined by mongoose.
where as in Document middleware this
return all fields that you defined not by mongoose so this.model
not your defined property. for above example I have name
property so you can get that by this.name
that will show your requested value. But when use this.contructor
then you will return instance variable that are defined by mongoose like return Model
instance variable.
Upvotes: 15
Reputation: 3781
You could use the name of the model variable instead of this
.
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var schema = new mongoose.Schema;
schema.add({ name: 'string' });
var Cat = mongoose.model('Cat', schema);
schema.pre('save', function (next) {
Cat.count(function (err, count) {
if (err) {
console.log(err)
} else {
console.log('there are %d kittens', count);
}
next();
});
})
var kitty = new Cat({ name: 'Zildjian' });
kitty.save(function (err) {
if (err) {
console.log(err);
} else {
console.log('meow');
}
});
Subsequent executions report the correct count and then perform the save operation.
$ node index.js
there are 0 kittens
meow
$ node index.js
there are 1 kittens
meow
$ node index.js
there are 2 kittens
meow
$ node index.js
there are 3 kittens
meow
And documents are being persisted in the database.
db.cats.find()
{ "_id" : ObjectId("5873b77454fc2a49fd7ec6cf"), "name" : "Zildjian", "__v" : 0 }
{ "_id" : ObjectId("5873b777c051094a0ad5dda2"), "name" : "Zildjian", "__v" : 0 }
{ "_id" : ObjectId("5873b7789aad6e4a15018ee8"), "name" : "Zildjian", "__v" : 0 }
{ "_id" : ObjectId("5873b77b7628684a24c90b07"), "name" : "Zildjian", "__v" : 0 }
Upvotes: 1