I have the following model for mongoose.model('quotes')
:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var quotesSchema = new Schema({
created: { type: String, default: moment().format() },
type: { type: Number, default: 0 },
number: { type: Number, required: true },
title: { type: String, required: true, trim: true},
background: { type: String, required: true },
points: { type: Number, default: 1 },
status: { type: Number, default: 0 },
owner: { type: String, default: "anon" }
});
var settingsSchema = new Schema({
nextQuoteNumber: { type: Number, default: 1 }
});
// Save Setting Model earlier to use it below
mongoose.model('settings', settingsSchema);
var Setting = mongoose.model('settings');
quotesSchema.pre('save', true, function(next) {
Setting.findByIdAndUpdate(currentSettingsId, { $inc: { nextQuoteNumber: 1 } }, function (err, settings) {
if (err) { console.log(err) };
this.number = settings.nextQuoteNumber - 1; // substract 1 because I need the 'current' sequence number, not the next
next();
});
});
mongoose.model('quotes', quotesSchema);
There is an additional Schema for mongoose.model('settings')
to store an incrementing number for the incrementing unique index Quote.number
im trying to establish. Before each save, quotesSchema.pre('save')
is called to read, increase and pass the nextQuoteNumber
as this.number
to the respectively next()
function.
However, this entire .pre('save')
function does not seem to trigger when saving a Quote
elsewhere. Mongoose aborts the save since number
is required but not defined and no console.log()
i write into the function ever outputs anything.
Mongoose | save() Function The save() function is used to save the document to the database. Using this function, new documents can be added to the database.
The save() function triggers validate() hooks, because mongoose has a built-in pre('save') hook that calls validate() . This means that all pre('validate') and post('validate') hooks get called before any pre('save') hooks.
The main difference is that with . save() you already have an object in your client side code or had to retrieve the data from the server before you are writing it back, and you are writing back the whole thing. On the other hand . update() does not require the data to be loaded to the client from the server.
While save() returns a promise, functions like Mongoose's find() return a Mongoose Query . Mongoose queries are thenables. In other words, queries have a then() function that behaves similarly to the Promise then() function. So you can use queries with promise chaining and async/await.
Use pre('validate')
instead of pre('save')
to set the value for the required field. Mongoose validates documents before saving, therefore your save
middleware won't be called if there are validation errors. Switching the middleware from save
to validate
will make your function set the number field before it is validated.
quotesSchema.pre('validate', true, function(next) {
Setting.findByIdAndUpdate(currentSettingsId, { $inc: { nextQuoteNumber: 1 } }, function (err, settings) {
if (err) { console.log(err) };
this.number = settings.nextQuoteNumber - 1; // substract 1 because I need the 'current' sequence number, not the next
next();
});
});
For people who are redirected here by Google, make sure you are calling mongoose.model()
AFTER methods
and hooks declaration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With