< BACK

Joins on MongoDB with Mongoose and NodeJs

If you don’t know, non relational databases (NoSQL) can’t do joins, that thing that helps you query two different tables in one simple query, something like:

SELECT posts.title, users.name FROM {posts} LEFT JOIN posts.userid = users.userid ….;

Document-oriented databases, like MongoDB, allows you to easily create collections and documents, and I thought the best way to do “joins” was to embed the user object in the post.author property inside the post object, but this presents a big problem, what happens if inside the user object you have fields like username or picture that the user can change? An update operation on all the posts would be crazy, and for each collection that you have that has a user object embedded in the model you would have to do an update just to change the picture. Ridiculous isn’t it? That’s what I thought.

Then, I spent some time saving just the user _id into the posts.author property, and every time I wanted to query the posts I would just do two queries, first, get the post, then with the post.author get the user. That’s also expensive and not very clean in your code. And if you’re doing loops (which I try to avoid because of the async/sync thing on Nodejs), you could run into problems really fast.

Introducing Mongoose and populate

It seems that with Mongoose (v3) is really, and I mean really easy to do “joins”. Yeah, I double quote joins because they are not really joins but from a result-oriented perspective (is there another one?) that’s what you’re doing.

Mongoose comes with a feature called “populate”. Let’s explain:

Suppose you have two models, Users and Posts, I’ll keep things simple for now.

var UserSchema = new Schema({

  username: String

})

var PostSchema = new Schema({

  title: String,

  author: {type: Schema.Types.ObjectId, ref: “User”}

});

That’s easy, we just define two schemas and in author we create a property that will be a reference to the User schema. On save, we will save the _id of the user object.

The fun part comes when doing a findOne or find:

var id = “some id of the post we want to query”;

Post.findOne({_id: id})

  .populate(“author”)

  .exec(function(error, result) {

    // do something with the result like render it

  })

What is nice about this is that Mongoose will do a query on the users collection and get the author of the post and embed it in the result. You’ve just done a join on MongoDB my friend.

More information about populate here: http://mongoosejs.com/docs/populate.html


Share this: