Code Smoothie

Foreign Keys and Other Cross-Collection Relationships in Meteor With collection-helpers

Take a look at my article about database normalization if you are not sure what it means.

A few days ago, I designed a pretty normalized database scheme to track event attendances in MongoDB/Meteor. To illustrate, here is a simplified version:


The users collection managed by Meteor’s built-in account system, with a custom profile.name field.

events

_id name date
123 Normal Meeting 1/12/2000

events_attendance

_id userId checkIn checkoutOut
abc 123 800 (8 AM) 1530 (3:30 PM)


I wanted to output the users.profile.name, events.date, events_attendance.checkOut/checkIn.

So what do I do?

I could use collection.findOne()

So I would do something like

var results = []

EventsAttended.find().foreach(function(doc){
    results.push({
        _id: doc._id,
        name: Meteor.users.findOne(
            {
                _id: doc.userId
            }).profile.name

        //...you get the point
    });
}

It is pretty simple, yet there’s also another way.

Using collection-helpers

I ended up using collection-helpers for its its simplicity, but you can choose to use the above method. This package helps you resolve your foreign keys by adding another field to your documents.

In this case, it allows us to directly jump to the results variable above, just by doing find() or findOne().

EventsAttended.helpers({
  name: function () {
    return Meteor.users.findOne({
        _id: this.userId
    }).profile.firstName;
  }
});

One more thing to worry about…

Since everything is loaded asynchronously, the data requested may not be available. This causes the application to crash.

So I just simply suppress the errors by wrapping it in a try-catch:

EventsAttended.helpers({
  name: function () {
    try{
      return Meteor.users.findOne({
        _id: this.userId
      }).profile.firstName;
    } catch(e){}
  },
});