Modify data in mongoose pre-validate hook - node.js

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();
});

Related

is changed function in sequelize like isModified in mongoose?

mongoose isModified functionIn a hook I want to confirm whether a password has changed before executing encryption process. Mongoose has a function "isModified" and I believe Sequelize's "changed" function servers the same purpose.
I cannot get the "changed" function to work. I am looking for an example of how it is used.
There is an example of how changed() works in the official documentation
const mdl = await MyModel.findOne();
mdl.myJsonField.a = 1;
console.log(mdl.changed()) => false
await mdl.save(); // this will not save anything
mdl.changed('myJsonField', true);
console.log(mdl.changed()) => ['myJsonField']
await mdl.save(); // will save
Keep in mind that changes are detected for the top-level fields and only for changes that were made since the last save call.

Mongoose - Post Hook - Change Doc/Model values after load & Before Returning

Solved: I can only guess that delirium got me.
sorry for not figuring it out before posting, but here's the solution for the next persons sake. The try/catch is not necessary, but it did help me get out some errors that were not being printed to console. If there is a better way to document solving my own problem, I'd appreciate the feedback.
Old Question
I have docs stored in my mongo db that I want to modify before being returned to a find() or findOne(). I want to do this without changing the values and a single hook for all find variants. Call it a masking. I'm actually normalizing a numeric value to a scale of 0 to 1. I do not want to modify the value in the doc, just change the values when the doc is returned via find, findOne. E.G. "Change Model values after load in Mongoose"
Solution
schema.post('init', function(doc){
try{
console.log(doc); // prints the doc to console, complete
doc.property = "new property value"; // changes the document value
console.log(doc); // returns the modified document
return doc;
}
catch(error){
console.log(error);
}
}
Old Notes
Other threads note usage of the post init hook. I have tried the methods in the following related topics with no success.
Mongoose - how to tap schema middleware into the 'init' event?
Change Model values after load in Mongoose (this method has changed with 5.x)
schema.post('init', function(doc){
console.log('Tell me i fired'); // works, prints to console
console.log(doc); // works, prints full model to console
doc.valueField = doc.valueField2+doc.valueField3; // fails, no doc returned, throws no errors
});
schema.post('init', function(doc, next){
console.log('Tell me i fired'); // works, prints to console
console.log(doc); // works, prints full model to console
doc.valueField1 = doc.valueField2+doc.valueField3; // fails, no doc returned, throws no errors
next();
});
I've tried adding return(doc);, doc.save() and just about every mutation of the above code I can compile in my shrinking mental capacity. I keep throwing crap at the wall and nothing is sticking. The documentation over at mongoose is poor and the behavior changed with version 5.x with the removal of Asynch call backs (dropped the next() ).
This is a bug submission on mongoose where the dropping of next() is noted.
https://github.com/Automattic/mongoose/issues/6037
release notes from the 5.x release
https://github.com/Automattic/mongoose/blob/master/migrating_to_5.md#init-hook-signatures
~ Edited, because i solved my own problem ~

Mongoose and bulk update

First time working with MongoDB and Mongoose.
I have written an edit function which do something with the input params and then call an update on the model:
edit: function (input) {
var query = ...
var document = ...
return Model.update(query, document, {multi: true});
}
The function return a Promise with the number of affected documents.
I know that the Mongoose update function
updates documents in the database without returning them
so I was wondering if there is a way to somehow:
run my edit function
if everything goes well, run a find on the model in order to retrieve the updated documents, and return the find's Promise.
Any help would be appreciated.

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
}

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

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.

Resources