J Cole Morrison
J Cole Morrison

J Cole Morrison

Startup Engineering, former Techstars Hackstar, AWS Solutions Architect and Culture guy. Based out of Sacramento, California.


MongoDB Joins with MongooseJS

Posted by J Cole Morrison on .
Featured

MongoDB Joins with MongooseJS

Posted by J Cole Morrison on .

If you're going to have a cow about doing something relational in NoSQL, go have a cow about anything ever that was used for something other than what it was originally intended.

So you're using MongoDB and Node. Let's pretend you have two collections of documents, "Users" and "Comments." There are two ways to "relate" this data. More info at this link:

MongoDB Data Model Design

Embedded Data Models, which would be like so:

> db.users.findOne()

{
    "_id": ObjectId("randomstringofcharacters"),
    "firstname": "Some",
    "lastname": "Lastname",
    "username": "Pipituu",
    "comments": [
        {
            body: "Some comment",
            date: "some date"
        },
        {
            body: "Another comment",
            date: "some date"
        }
    ],
    "password": "abc123"
}

So, these allow you to make one query and get everything vs. multiple ones. The problem with this model from a Mongo stand point is only that if it grows to large, you'll have to allocate more memory for it. However, for those who want to use MongoDB for relations, doing it like this is just a headache. If you want to "relate" the comments to another user, or to other comments, the best bet is to do it in a normalized style.

So we'd do it like so:

A User:

{
    "_id": ObjectId("randomstringofcharacters"),
    "firstname": "Some",
    "lastname": "Lastname",
    "username": "Pipituu",
    "comments": [
        ObjectId("idofsomecomment"),
        ObjectId("idofanothercomment")
    ],
    "password": "abc123"
}

A Comment:

{
    "_id": ObjectId("idofsomecomment"),
    "body": "Some comment",
    "parent": ObjectId("idofthiscommentsparent"),
    "moreMetaData": "more meta data"
}

Okay, enough of a primer, let's figure out how we'd join these together with Mongoose. And yes, you'll want to use something like Mongoose.js to simulate joins "easily." Otherwise, you'll need to query the User and then, in your programming language, use the Comment Ids to grab the related comments (which is all Mongoose does in the background).

Mongoose.js's Populate

This is the function one uses to populate documents. Let's pretend the data above is in our MongoDB. To get it join a User with all their appropriate Comment's together you'd just do the following:

This is assuming you've created a mongoose schema for Users and Comments.

// Find the user doc
Users.findById('randomstringofcharacters')

// This is just chaining with mongoose
// Here, we select the 'comments' field
// to be populated
    .populate('comments')

// finally, you just run it.
    .exec(function (err, client) {
        if (err) {
            console.log(err)
        }

        // This will now have comments embedded!
        return client;
    });

The client that you return will now have the comments embedded. A gotcha that you have to remember is that, every time you create a comment, you need to insert it's ID into the relevant user's comments array.

I'll be covering this more in-depth in the series of articles I put out on building apps with angular and express. By in-depth I mean, doing a step by step process of how it's done, instead of just a quick summary.

J Cole Morrison

J Cole Morrison

http://start.jcolemorrison.com

Startup Engineering, former Techstars Hackstar, AWS Solutions Architect and Culture guy. Based out of Sacramento, California.

J Cole Morrison

J Cole Morrison

Startup Engineering, former Techstars Hackstar, AWS Solutions Architect and Culture guy. Based out of Sacramento, California.