MONGOOSE Tips and Tricks for Uncommon Cases

27 / Jun / 2017 by Rachit Jain 0 comments

Mongoose is an object modelling package for Node that essentially works like an ORM for many popular languages much like Hibernate is for JAVA. Below are some of the mongoose special scenario(s) I stepped upon while working on the project. It took me some time to figure it out. Hopefully below details would prove helpful to you thereby improving your productivity while working with mongoose.

1) Updating array objects and calling save:

Suppose you have a user schema which goes something like this:-

var UserSchema = new Schema({
  name: 'String',
  emails: [],
  username: 'String',
  age: 'Number'
});

I want to update the recoveryMail address of a particular user having an entry in emails property something like:

emails: [{
	provider: 'gmail',
	id: 'abc@gmail.com',
 	recoveryMail: 'def@gmail.com
},
{
	provider: 'hotmail',
	id: 'abc@hotmail.com',
	recoveryMail: 'def@hotmail.com
}];

Now if I try to fetch a particular user and update its recoveryMail property and try calling save function. My changes won’t get reflected in Mongo until I provide the full path of the property changed inside the object of the array, particularly because mongoose is unable to identify changes in objects present in the array.

In this case, it would be something like this:

user.emails[0].recoveryMail = 'fgh@gmail.com'; // user is the object received on firing a find query using mongoose
user.markModified('emails.recoveryMail'); // One need to provide the full path of the property getting changed in array of objects

2) Auto conversion while using find and aggregate query:

var User = mongoose.model('Users', UserSchema);
User.find({
	age: '26 // here we are passing value as string although age is Number type but it works as mongoose converts it 	for us
	}, function(err, users){
		console.log(users); // print users that matches the criteria
});

On trying to run the same with aggregate queries one expect mongoose to once again come in the picture and does conversion logic for us before firing a query but mongoose does not do so in a case of aggregate queries:

User.aggregate({
	$match: { age : '26' }
}, function (err, users){
	console.log(users); // we wont get any records here
});

In a case of aggregate queries, you have to take care of conversion by your own as mongoose magic does not work when working with aggregate queries, so queries containing more sophisticated logic needs to be handled more accurately when it comes to Data Types.

3) When you query using a model, and in the result, you see a bunch of fields, but when you try to access them you get undefined.

var User = mongoose.model('Users', UserSchema);
User.find({}, function (err, users){
users.forEach(function(user) {
	console.log(user); // this will print something like {'name':'harsh', 'fullName': 'abc@abc.com'}
	console.log(user.email); // this will print 'undefined'
});

There is no virtuals for fullName that is set. It’s just that value which was set somehow and when I log the whole object I can see the property along with its value present there, but I won’t be able to access it simply because my schema does not contain a definition for that property. So I need to update my schema to contain the property before I can start accessing the same.

FOUND THIS USEFUL? SHARE IT

Leave a comment -