MongoDB “Eager Fetching” Workaround in GeddyJS

As you all know, there’s no such thing as a JOIN in MongoDB. The burden of applying logic is on the application side.

SQL Adapters (like MySQL and PostgreSQL) have an eager fetching solution from the GeddyJS Model ORM. Eager fetching would look like this (taken from the code sample in the GeddyJS tutorial):

this.index = function (req, resp, params) {
  var self = this;

  geddy.model.ToDo.all({}, {includes: 'steps'}, function(err, toDos) {
    if (err) {
      throw err;
    }
    self.respondWith(toDos, {type:'ToDo'});
  });
};

This would definitely work for an SQL Adapter.. but what about MongoDB with linked collections? The GeddyJS dev team might put this feature up in the future but it has yet to be done.

So let’s do a workaround for now! Let’s assume that we have two separate models (and collections) named ToDo and Step.

this.index = function (req, resp, params) {
  var self = this;

  geddy.model.ToDo.all(function (err, todos) {
    todos.forEach(function(todo) {
      todo.getSteps(function (err, steps) {
        todo.steps = steps;
      });
    });

    self.respondWith(todos, {type: 'ToDo'});
  });
});

But wait, there’s more!

There can be a slight performance issue with this and it may be evident in production code. Remember that callbacks are asynchronous and if the callbacks haven’t finished and you already responded, the data might end up as undefined.

How do we handle this properly? Check out this blog post (How to Properly Deal with Javascript Asynchronous Code: Matteo Agosti) which explains how to treat asynchronous code and callbacks in NodeJS.

Now let’s apply it to the code above:

this.index = function (req, resp, params) {
  var self = this;

  geddy.model.ToDo.all(function (err, todos) {
    todos.forEach(function(todo) {
      todo.getSteps(function (err, steps) {
        todo.steps = steps;
      });
    });

    setTimeout(function() {
      self.respondWith(todos, {type: 'ToDo'});
    }, todos.length * 1000); // Just to factor in length of the todos array
  });
});

Also, if you’d prefer, you can also use a different ORM. Chances are you’ll have to use the same logic for most if not all current MongoDB compatible ORMs however. My previous post talks about using another ORM (Mongoose) to query embedded documents.

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload the CAPTCHA.