Archive

June 2015

Browsing

I have been working with Sails.JS for a little while now and would like to share a bit of information on how to use the Models and Waterline/ORM (Object Relational Mapper) when working with your database. An ORM is basically an API to access your database and perform queries against it. Waterline as an ORM has built-in adapters that allows you to use MS SQL Server, MongoDB, Redis among a host of others. It simplifies the process of working with a database since you’re using the same API regardless of what database you’re using (see Waterline on GitHub to see if there’s an adapter available for your database).

You can use Waterline in any flavor of Node.JS but in this post, I’ll be discussing Waterline in the context of Sails.JS although the implementation and concepts are pretty much the same. The adapter should not be relevant in most cases but certain databases have other functionalities that other databases doesn’t so this is something that you need to be aware of. A simple example of this would be if you’re using a relational database such as SQL Server that allows you to add precision or size to the column property (ie. nvarchar(128).

{
    name: { 
        type: 'string',
        size: 128
    }
}

To keep things simple, I’m also going to use from the NoSQL perspective as the context of the post although like I have mentioned, the examples will handle most cases and scenarios.

Models

A model essentially describes a table/collection in your database and makes up the definition of properties or attributes and what it can contain. Model usually maps to your database table or collection. By having defined models, you are adding constraints on what properties/fields that can be saved.

Each model consists of one or more attributes which can be of type string, int, etc. (see more below). A model is synonymous with Collection as each collection can contain many Models.

Globals

All models assuming that they’re stored (by convention) where they need to be, is accessible globally by default. A model such as User that is in /api/models/User.js can be accessed anywhere simply by doing User.findById(1). This Sails.JS feature can be configured to be turned off in the /config/globals.js.

Attributes

Here’s an extensive list of all the attributes that you can use but I’d like to go over some basics. The most common types that you’ll probably going to be using are string, datetime, email, boolean, integer, array and an object (I’ll discuss this below when I go over creating relationships).

Let’s say that we have a user registration system where we need to store some basic user information. You can define a User model such as:

model.exports = {
    name: {
        type: 'string',
        required: true
    },
    lastLoggedIn: {
        type: 'datetime',
        defaultsTo: new Date()
    },
    favoriteNumbers: {
        type: 'array'
    },
    email: {
        type: 'email',
        unique: true
    }
}

I have included a variety of options so you can see what is possible and give you a sense of what that can look like.

The name property is set to a type of "string" which allows all character types that is set to required. The lastLoggedIn is of a "datetime" and defaults to current date if not provided. The favoriteNumbers property is set to an array which basically allows you to pass in array. Most of the property types are very basic and determined by your applications requirements including defaults, etc.

The email property in this case is of type "email" and is set to unique (meaning an error will be thrown if you insert the same email twice). Being an "email" type validates that this the string passed in is in the form of an email address but under the covers, it’s still a "string" type.

If you’re working against a NoSQL database backend, setting the property as unique isn’t enough (the only thing that is unique is its id object, so it has to be configured in the /config/bootstrap.js to ensure that the database indeed does not allow duplicate email by (see code below).

// Bootstrap.JS
module.exports.bootstrap = function(cb) {
  User.native(function(err, collection) {
    collection.ensureIndex('email', {
      unique: true
    }, function(err, result) {
      if (err) {
        sails.log.error(err);
      }
    });
  });

  // Trigger the callback to finish up the bootstrap process
  cb();

  _.extend(sails.hooks.http.app.locals, sails.config.http.locals);
};

Next up, I’d like to go over the database relationships as this is essential in more complex applications.

1-to-Many Relationship

NoSQL databases in general are document based so you can essentially store all data that pertains to that collection in a single document (nested data). There’s also scenarios where having your data in separate documents might be a good idea depending on your application’s needs. Storing data in different documents can be a good idea if you do a lot of "writes" but if your application is mostly "reads" then it makes more sense to go with a single document approach.

Since we’re in discussion of relationships, we will work with an example that consists of multiple models/collections. I’ll go over an example of 1-to-many relationship then further extend the example into the many-to-many relationship type.

For example:
A model User has UserTypes associated with it.

You can build out your models such as:

// User.JS
module.exports = {
    identity: 'User',
    attributes: {
        name: {
            type: 'string'
        }
        userTypes: {
            collection: 'UserTypes',
            via: 'user'
        }
    }
}
// UserTypes.js
module.exports = {
    identity: 'UserTypes',
    attributes: {
        user: {
            model: 'User'
        },
        userType: {
            type: 'string'
        }
    }
}

If you look at the defined models, User has an identity which is an optional property that allows you to set the name of the model to other than the default. You can set "User" to "foo" if you’d like to better describe the model. The attribute of userTypes. userTypes is specified as a collection of UserTypes model and points to the UserTypes via the user property. This defines a 1-many relationship between the User and UserTypes model.

On the other hand, UserTypes model simply just have the property of user which maps back to the User model. Using the example model above, the querying can be illustrated in the next section for ORM queries and how we can leverage this relationship.

Many-to-Many Relationship

Using the same models as above, we can define a many-to-many relationship using the concept of "followers" as an example. Twitter has this concept of allowing a user to follow other users and vice versa, hence the many-to-many relationship. Let’s look at an example how that model relationship looks like when building the models.

// User.JS
module.exports = {
    identity: 'User',
    attributes: {
        name: {
            type: 'string'
        }
        userTypes: {
            collection: 'UserTypes',
            via: 'user'
        },

        // Reference to user followers
        userFollowers: {
            collection: 'UserFollower',
            via: 'user'
        },

        // Reference to users that the user is following
        userFollowing: {
            collection: 'UserFollower',
            via: 'follower'
        }
    }
}
// UserFollower.JS
module.exports = {
    identity: 'UserFollower',
    attributes: {
        user: {
            model: 'User'
        },

        follower: {
            model: 'User'
        }
    }
}

In the example above, I have extended the User model with 2 new properties namely userFollowers and userFollowing. The property definition are both set to the same collection UserFollower and uses the via object property that points to the UserFollower properties.

On the other hand, UserFollower have 2 properties as well that has a model specified as the User that points back to the User model.

In the next post (part 2), we will be exploring the ORM piece and re-use the examples in this post to perform basic and more advanced queries. Please let me know if you find this post useful. Feel free to comment as well for feedback and share it with others in your social media. Thanks for reading.

Thank you and keep shipping!

I get asked a lot on how I’m able to learn something new in a short period of time. In a sense, I’m a naturally curious person and learning is something that I’ve been doing for my whole life. After college, I kept on reading books and constantly educated myself in various subjects.

In this post, I’d like to share what I believe are the key ingredients to successful learning. I’d like to highlight some key points that leads me to better learning that might help some people along the way. It is worth recognizing that understanding the learning process is the key to successful learning. It is important because the process is being internalized as to "how" to learn and "why" learning something is or isn’t working.

Starting with a goal in mind

This is answering the "why". Finding out the reasons why you’re trying to learn something as opposed to just passively being curius about it is crucial to making things stick. You need to convince yourself on why learning something new is worth your time. You need hold on to those reasons when learning becomes tough. Knowing why you want to learn something to begin with is important as this sets a clear vision statement on what you define as "success". You cannot embrace success if you don’t know what it is. Walking or going on a journey without a clearly defined destination leads to nowhere.

Breaking up things into small chunks

Once the purpose of the learning and why you want to learn something has been defined then the next step is to create a "blueprint" or laying down a "road map". This constitutes the things that you will need to focus on, one piece at a time. Making a list of these things identifies can unclutter the mind and instead put things in perspective.

In terms of learning a new programming language or framework, instead of saying, I want to learn "Node.JS", instead you have to be specific on which part of Node.JS you want to learn first. Learning and mastering Node.JS is a huge undertaking since there’s several web frameworks out there (Express, SailsJS, etc) including the vast amount of middleware and libraries that the open source community has created.

I find that finding out the fundamentals and what those things entails.
Breaking things down also makes the concepts digestable and not overwhelming.

Knowing your strengths

Over the years, I have found different ways to learn new things, particularly learning new programming languages or technologies. There is not one technique that applies to everyone. Maybe writing down some concepts helps reinforce the knowledge or maybe you like learning in a classroom setting. Whatever it may be, it helps to understand your unique way of learning.

What works for me however is a combination of different things. I use Evernote heavily to write down ideas that I’d like to remember for future reference. I consider myself a visual learner, so I rely on watching a lot of videos whether it’s on YouTube or some video course website. On a given subject/topic, I’d watch not one or two, but several of them so I can see the different variations and perspective on the subject matter. If that’s not enough, I’ll read a book or two.

After having some sense of what I just learned, I put it into practice. This is very important and all that learning wouldn’t matter if not put into practice. This step validates if whether you have learned anything and to give you the confident to move forward into another subject.

100% focus

I always find that if I’m not "present" and 100% into what I’m trying to do, my efforts is just a waste. If you really want to learn something and make it stick, then spend at least an hour of every waking day to facilitate that learning process.

Patience

Learning something new could potentially become many weeks, many months or even years but having the strength to pursue learning obstacles is another crucial piece. You need to be able to adjust and not be frustrated when something becomes difficult to understand.

Teach

I firmly believe in the idea that if you can’t explain or define something then you don’t really know what it is. The same holds true about knowing versus truly understanding something. If you have an opportunity to teach what you have learned to someone and actually verbalize the ideas, it will help even more with reinforcing what you have learned.

You will also think deeper about the concepts and new things will come up that will force you to do further research on some underlying topics.

Conclusion

I hope that this helps. Everyone has their own unique way of learning and what may work for someone may not work for you.