MongooseJS and the problem with adding new properties

Hold on Cowboy

This blog post is pretty old. Be careful with the information you find in here. It's likely dead, dying, or wildly inaccurate.

My setup is easy. Node.js, ExpressJS, MongooseJS.

The Problem 

I was getting a list of objects from the MongoDB. Like this

// Find all items where owner in following array
Thing.find()
    .where('owner').in(following)
    .populate('owner')
    .populate('comments.userId')
    .sort('-updatedOn')
    .limit(20)
    .exec(callback);

In the callback I was assigning the results to res.locals.things for use in another middleware function.

In another middleware function I tried this

// Extend thing[i] with a new property called newProperty
for var i=0; i < res.locals.things.length; i++) {
    res.locals.things[i].newProperty = 'hello';
}

When I would echo out my things, newProperty was not in there.

To make a long story short. You can’t add new properties to MongooseJS Models. The solution is to not have MongooseJS create Models from the query above, just plain old JavaScript Objects. This can be accomplished via the lean(true) switch in the query. So now my query looks like this

// Find all items where owner in following array
Thing.find()
    .where('owner').in(following)
    .populate('owner')
    .populate('comments.userId')
    .sort('-updatedOn')
    .limit(20)
    .lean(true) // Only return JSON objects, not MongooseJS Models
    .exec(callback);

Now I can extend the response with custom properties.

Additionally 

I tried using MongooseJS virtual attributes, but this would not let me save it to a new property. So this code crashed with an error of RangeError: Maximum call stack size exceeded

ThingSchema.virtual('newProperty').set(function(num) {
    this.newProperty = num;
});

Resources 

http://mongoosejs.com/docs/api.html#query_Query-lean