Mongoose - how to tap schema middleware into the 'init' event? - node.js

It is suggested in the Mongoose docs that I should be able to control the flow using middleware that plugs in to the "init" hook.
However, I have so far had success only with "save" and "validate".
When I do something like this, neither of these middleware ever get called:
MySchema.post( "init", function (next) { console.log("post init") });
MySchema.pre( "init", function (next) { console.log("pre init") });
Am I missing something?

It turns out that the "init" event/hook is not fired when creating a new Model, it is only fired, when loading an existing model from the database. It seems that I should use the pre/validate hook instead.

I have successfully used middleware like MySchema.post('init', function() { ... }); with Mongoose which is then executed for each model instance loaded in a find query. Note that there isn't a next parameter to call with this middleware, it should just return when done.

Related

Modify data in mongoose pre-validate hook

I would like to modify a document field's data prior to it being validated by mongoose, like so:
mySchema.pre("validate", function (next) {
this.myField = "yay a new value prior to validation" // doesn't work for me
next();
});
Unfortunately, that doesn't work for me. The example above is simplified, in my project I'm trying to prevent an ObjectParameterError from crashing my server, and assigning values in my pre-validate hook doesn't work for me.
Try using .set() method of mongoose Document to access value. Your code should be changed this way
mySchema.pre("validate", function (next) {
this.set("myField", "yay a new value prior to validation")
next();
});

Node.js update db object on save event in another

What is the most convenient way to create/update object on saving changes to other? Imagine we have a model Client and we emit event on save.
clientSchema.post('save', function (client) {
process.emit('clientUpdate', client);
});
Then we can subscribe for that event like:
process.on('clientUpdate', function(client) {
//LOGIC GOES HERE
});
Let's assume we want now to update ClientProjection. Where you would locate the listener and how you would implement update logic for mongoDB(mongoose)- using model, by dao, etc.?
I believe that you can avoid emitting another event and just make the update within the post-save hook. For example:
clientSchema.post('save', function (client, next) {
ClientProjection.update( {/* Query Parameters */},
{/* Data to update */},
function(err, clientProjection) {
next()
}
});
In a post-save hook, if you want to call an async function, you'll need to add next as your second argument and invoke it in the callback when the async action is complete. See the Asynchronous Post Hooks section of the mongoose Middleware docs

How to save object immediately in MongoDB?

In my Node application I use the mongoose module.
I found out that after
model_name.create({...})
object is not created immediately but with some delay (buffer?).
How can I force to save this new object in this particular moment?
Mongoose inserts the value inmediatly.
The problem is that you are not using it´s callback. Try to code this way:
//There is the definition
Customer.create(YOURDATA, function (err, obj) {
if (err) {
//This will be executed if create is going bad.
return handleError(res, err);
}
//This code will be executed AFTER SAVE
console.log(obj._id):
return res.json(201, obj);
});
Callback functions will be automatically executed by mongoose after the CREATE function has been executed in BD.
In obj, you will receive the saved object from DB, and then you will be able to access its properties.
Anyway, there you have some documentation:
the mongoose docs about callbacks
Some docs about Async methods:
Hope it will solve you problem

Find if object is changed in pre-save hook mongoose

I am trying to find if the object is changed in pre-save and do some actions accordingly. Followinfg is my code
var eql = require("deep-eql");
OrderSchema.post( 'init', function() {
this._original = this.toObject();
});
OrderSchema.pre('save', function(next) {
var original = this._original;
delete this._original;
if(eql(this, original)){
//do some actions
}
next();
});
It returns false even when I don't change anything!
First of all, you don't need the original object at all. You can access it in the pre hook via this. Secondly post hook executes only after all pre hooks are executed, so your code doesn't make any sense at all (check mongoose docs).
You can do the check by checking isModified in your pre hook and remove the post hook at all.
OrderSchema.pre('save', function(next) {
if(!this.isModified()){
//not modified
}
next();
});
Update
In order to check if some property was modified, pass property name as a parameter to isModified function:
if (this.isModified("some-property")) {
// do something
}

Having trouble understanding how the pre() function in Mongoose is working in this code snippet

I am learning how to make web apps with node.js. I have been following the tutorial provided by Alex Young. I am having trouble understanding how the pre() function works in Mongoose. I have read the Mongoose API documentation and understand that it is a way of "chaining" functions to an existing one, but I do not understand how it is actually working when I look at a code example (see below code snippets).
My question is what is going on in the here? There are three functions involved here (userSaved(), userSaveFailed(), and the password validation function defined in the pre() function). How are these function related to each other in terms of order in which they run? Is the actual saving of the document into the database completed before userSaved() and userSavedFail() are run?
I admit that my lack of understanding understanding may be due to my lack of knowledge on javascript (I come from a PHP background), but I just can't follow what is going on in this code.
Modified save behavior define in models.js :
User.pre('save', function(next) {
if (!validatePresenceOf(this.password)) {
// Through error if password fails validation.
next(new Error('Invalid password'));
}
else {
next();
}
});
Call to save data to database from app.js :
app.post('/users.:format?', function(req, res) {
var user = new User(req.body.user);
function userSaved() {
switch (req.params.format) {
case 'json':
res.send(user.__doc);
break;
default:
req.session.user_id = user.id;
res.redirect('/documents');
}
}
function userSaveFailed() {
res.render('users/new.jade', {
locals: { user: user }
});
}
user.save(userSaved, userSaveFailed);
});
In my opinion,the function followed by "save", is the method which gets executed before the save function is called(as the function name "PRE" imply).
The first function that is ran is user.save() passing in two callbacks, one for if user.save() completes without errors (userSaved) and another if it fails (userSavedFailed)
User.pre('save', function(next) {
if (!validatePresenceOf(this.password)) {
// Through error if password fails validation.
next(new Error('Invalid password'));
}
else {
next();
}
});
This code is running a set of asynchronous functions in parallel, only returning a response once all the functions have completed. In this case it returns by calling a callback function (userSaved or UserSavedFailed). Which is called depends on whether there was an error during the process of any of the functions.
The Async Module also chains functions and allows them to run synchronously or in parallel and may provide some examples of how this is accomplished to help you better understand what's actually happening.

Resources