Mongoose pre check hook do not shoot

I am trying to create a model and then create another model and save the link to the original model using mongoose. I am looking at mongoose documentation on middleware and their hooks, but some of them don't seem to work.

This answer tells me why my init-hook does not start HERE , pre and post init only when loading a previously existing model from db. So I read that validate will work when creating a new model. Knowing that I switched from pre init to pre validate .

Here is the code for what I'm trying to do:

 GroupSchema.pre('validate', function (next, data) { console.log("inside pre validate"); if (data.location) { location = new Location(data.location); data.location = location._id; location.save(function (err) { if (err) handleError(err); }); } next(); }) 

I know that I cannot use this because the document is not yet populated with data. That's why I have data , but it still does not work, oh, I got the parameters that I have to pass from this answer .

Any help would be appreciated.

************** ************** UPDATE

To add some clarity, using what was recommended in the answer and changing my pre validate function to the following:

 GroupSchema.pre('validate', function (next, data) { console.log("inside pre validate", this); if (this.location) { location = new Location(this.location); this.location = location._id; location.save(function (err) { if (err) handleError(err); }); } next(); }) 

I get the following error

 service err: CastError: Cast to ObjectId failed for value "[object Object]" at path "location" 

This makes sense because in my model it expects an ObjectId , not the [object, Object] that I pass. However, I thought I could save the location , get the ObjectId that was generated, and save it in the group model before it throws an error. Therefore, initially using pre init , until we find out that this will not work, and now find out that pre validate will not work either. Is there a way to do what I'm trying?

Here is what I am trying in sequence:

  • create location
  • get a new ObjectId
  • save the new location of the ObjectId in the group instead of the object itself

The reason I tried to add this to pre is because I could have this code in one place, and it would automatically handle this when creating a group model.

+5
source share
3 answers

What you are trying to do is not suitable for validate or any other middleware, because you need to provide location data along with what is needed to create the group itself.

It would be best to create a static method on GroupSchema that explicitly performs this extended create function.

So, assuming basic layouts and groups, for example:

 var LocationSchema = new Schema({ city: String, state: String }); var GroupSchema = new Schema({ name: String, location: {type: ObjectId, ref: 'Location'} }); 

Add a static method to the group diagram and register the models:

 GroupSchema.statics.createWithLocation = function(group, location, callback) { Location.create(location, function(err, location) { if (err) return callback(err); group.location = location._id; Group.create(group, callback); }); }; var Location = mongoose.model('Location', LocationSchema); var Group = mongoose.model('Group', GroupSchema); 

Call the new method, passing the group and location data parameters separately:

 Group.createWithLocation( {name: 'group1'}, {city: 'New York', state: 'NY'}, function(err, group) { console.log('group created with location: ', group); } ); 
+5
source

pre (validate) triggers before ".save" and note that the data does not have the current document. The variable "this" will have this. Also note: .pre (validate) will fire whenever we do ".save" The following is an example of how to do what you are looking for. I worked on this and it works great.

  var mongoose = require('mongoose'); var Schema = mongoose.Schema; //group schema var GroupSchema = new Schema({ location: String, pass: String }); //dependant location schema var LocationSchema = new Schema({ city: String }); //here I compile it into a model -groupschema var Groupuser = mongoose.model('usertest', GroupSchema, 'usertest'); //here I compile it into a model-location schema var Location = mongoose.model('locationtest', LocationSchema, 'locationtest'); //here is the pre validate,note this will trigger when we save groupschema realted documents. GroupSchema.pre('validate', function(next, data) { //will be triggered before the save console.log("inside pre validate", this); //the this will have amsterdam,and test see below. if (this.location) {//will be amsterdam var location = new Location(); location.city = this.location//adding amsterdam to the location.city location.save(function(err, data) {//this data will have the location document that we just saved. }); } next(); }); //now I create a new user for groupschema var newuser = new Groupuser(); newuser.location = 'amsterdam'; newuser.pass = 'test' newuser.save(function(err) { //Before this save function does the save,it triggers the .pre(validatE) if (err) return console.log(err);// }); 

I might not have nailed the internal location functionality the way you want, but I'm sure .pre (validate) triggers only when you do .save. This may be a new document or an existing doucment. Also note that it does not start when the model loads.

 1)we define a schema (var schema=new Schma({datatypes}) 2)we compile it into a model(var model=mongoose.model('collectionname',schema) 3)we instantiate a new variable of the model(var user=new model(); and then define the values 4) finally we save the data(user.save()->its here that the pre.validate triggers Hope its clear now 
+1
source

Most likely, your problem was that next() is called after the location is actually saved, as it is called asynchronously .

If you add next() inside save() , I believe that you should solve your problem.

 GroupSchema.pre('validate', function (next, data) { console.log("inside pre validate", this); if (this.location) { location = new Location(this.location); this.location = location._id; location.save(function (err) { if (err) handleError(err); next(); }); } else { next(); } }) 
0
source

Source: https://habr.com/ru/post/1209487/


All Articles