GeddyJS, MongoDB, and Querying Subdocs? Try Mongoose

For the past few months I’ve been working on studying NodeJS. Currently, I’m trying to work with the GeddyJS Framework (geddyjs.org). Now they have a database agnostic ORM built into it that can support the likes of MySQL and PostgreSQL but also MongoDB and even flat files.

Unfortunately, there are some things that can’t work very well with the built in ORM (like MongoDB though it does have some functionality) and you might end up on your own there while some things aren’t supported. Now it’s still possible to use a different ORM so don’t npm remove yet!

For example, you have a schema that looks like this:

var Deck = function () {

  this.defineProperties({
    title: {type: 'string', required: true},
    cards: {type: 'object', objectProp: [{name: 'string', type: 'string', id: 'string'}]}
  });

...

Now let’s say you wanted to find all Decks that had a certain card name in it. You can’t use the built in Geddy Model ORM for that yet.

Come in MongooseJS (mongoosejs.com). Actually you can use any other ORM for that matter but for simplicity’s sake let’s use Mongoose.

In your deck controller, let’s say you may have a GET parameter for the index action. Otherwise, it just lists down everything. So if there’s a GET parameter “card”, then you run the query using mongoose. In this example, if there’s no card parameter, the Geddy ORM is used instead.

var mongoose = require('mongoose');

var Decks = function () {
  this.respondsWith = ['html', 'json', 'xml', 'js', 'txt'];

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

    if(params.card) { // If card is specified, use mongoose
      // Connect to mongoose
      mongoose.connect('mongodb://localhost/sampledb');

      // Create Deck Schema
      var Deck = mongoose.model('Deck', { title: String, cards: [{name: String, type: String, id: String}] });

      // RegExp used for ignore case
      Deck.find({'cards.name': new RegExp('^'+params.card+'$', "i")}, function(err, decks) {
        if (err) {
          throw err;
        }

        // Must add model type for each deck
        decks.forEach(function(deck) {
          deck.type = 'Deck';
        });

        self.respondWith(decks, {type:'Deck'});
      });
    } else { // No card param. Use Geddy ORM
      geddy.model.Deck.all(function(err, decks) {
        if (err) {
          throw err;
        }

        self.respondWith(decks, {type:'Deck'});
      });
    }
  };

...

IMPORTANT: I just put in all the mongoose code inside the if statement for example’s sake but don’t initialize schemas in your controller. Please observe best practices and I highly suggest you have a different setup for your Mongoose schema and models and then just import them into your controller (lines 10-14).

One comment

  1. […] 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 […]

Leave a Reply

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