The last few weeks we have focused on web service design using Node.js with Express. So far we have covered getting started with express, using EJS to create web pages, and creating a push notification server. Today we will go over how to save data on your node project by using MongoDB.
This post will assume that you have MongoDB installed on your machine already. Check out the MongoDB Installation page if you do not have it setup.
First, let’s go over MongoDB a bit. MongoDB is a document oriented database. This allows you to just shove whatever JSON you want into it. You don’t have to declare a table structure like you do in SQL. You don’t even need to declare your collections at all. If you try to use a collection that doesn’t exist it just gets made for you immediately. Documents are stored in collections that you define, but documents within a collection don’t have to be similar at all. MongoDB also features an amazing query system. Imagine we want to store information about fruit. We could do the following:
We now have a fruit collection containing one fruit: an apple. Let’s add a few more:
Now we have a strawberry and an orange in our fruit collection. To get all fruits in our collection that come from trees we would do:
If we wanted to find all fruits that are red we would do:
And to find all fruits that are yellow or orange we would do:
Now apples can be green too. Let’s modify our apple entry to reflect that:
There are a few interesting things to be aware of when updating a document. By default, mongodb will only update the first entry it finds. You can set the multi option to force it to update every entry that matches the query. Also, note the $push operator I have included in the update object. That is telling mongo it will be adding an entry to an array on the document. If you left off push and just did:
You would be very disappointed. Setting no update operator will replace the document completely:
So what if you wanted to update a field that isn’t an array? You use the $set update operator:
MongoDB is very powerful and an excellent document store, but it lacks the join power that SQL brings to the table. You can join documents together by their _id field using MonoDB’s populate, but it’s not nearly as fast as what you can do with a few SQL joins. I encourage you to explore MongoDB as an option for your databases, but it’s important to approach your database design differently with MongoDB than with SQL. Be sure to check out the documentation for all you can do with MongoDB.
So how to we start using Mongo with Node? There are several libraries available on npm for connecting to Mongo, but I will be focusing on Mongoskin and Mongoose.
Let’s go ahead and get Mongoskin out of the way. Mongoskin is what you want if you just want to run basic MongoDB commands and nothing more. To get started add Mongoskin as a dependency:
And then in node:
Mongoskin is very easy to use and most MongoDB commands are supported. It has its issues, but if you want something simple to connect to a mongo database look no further. If you want the best MongoDB experience you can find with Node, keep reading!
On to Mongoose. As they say on their website: “Mongoose provides a straight-forward, schema-based solution to modeling your application data and includes built-in type casting, validation, query building, business logic hooks and more, out of the box.” Mongoose is a delight. To get started add Mongoose as a dependency:
It’s nice that MongoDB doesn’t need to have schemas, but it’s great that Mongoose gives them to you. Let’s put together a schema for our fruit collection:
Most of the schema above should be straight forward. Name must be a string or Mongoose will remove the property from the object before using it as a model. Color must be an array of strings. Source must be a string, and if it’s not present Mongoose will automatically set it to “tree”. Default values will not get stored in the actual database, but they will be applied when Mongoose pulls them out. The virtual “numberOfColors” will add a property automatically. Virtuals are great for properties that can be calculated based on the existing data on the model.
To use the fruits model:
The examples above barely scrape the surface of what you can do with MongoDB and Mongoose. Do yourself a favor and explore the possibilities of a document oriented database backed by MongoDB.
If you have been following along with our series on how to create your own web server, you should now be familiar with node.js and Express. Node.js lays the groundwork for the web server and Express builds upon it. If you haven’t already, I recommend that you take a look at the previous blog posts on Node.js and Express before we get started.
This use statement means that when you visit your project in a web browser, Express will look in the routes folder for a file called index.js that will tell the browser what to do. Right now, the index.js file should look something like this:
Right now, the Express router has one interaction that will render the home page. Currently, when there is a GET request to the route ‘/‘, Express will render the view found in views/index.ejs. The first argument for the render function is the name of the view file, and the second is an object that will be passed to the view file when it is rendered. This object can be used by EJS to change what is rendered on the page, without having to write an entirely new view. Right now the view will only render two lines of text. We are going to expand on this in order to show some dynamic content in the browser.
Rendering with EJS
We simply add a new property to the object we are sending to the render function. The property items is an array containing three strings. Now we will print these strings in our EJS file.
We create a for loop that will iterate through the array we passed from our Express function. The loop is places inside <% %> tags because we do not want the for loop itself to be added to the web page. Inside the loop, we have a <li> tag that will place an item on the web page for each item in the array. To display the item from the array, use the tag <%= items[i] %>. This will look up the element in the items, array, and add it to the web page. As you can see, these tags can be place anywhere inside normal html. To view these changes, just restart the server and reload the page in your browser. You should see something like this:
Dependencies and upgrading
If your project is built with Alloy, good news! An older version of Backbone ships with Alloy by default, as well as its underscore dependency. If you’re maintaining a classic Titanium project, you can download the most recent version of Backbone and underscore from here and use them like normal commonjs libraries. Additionally, we have provided an updated version of Backbone that has been modified to work with the current version of Alloy. To use it in an Alloy project, just place the minified version in your lib folder and add
An aside on the topic of mixins
On to the main Backbone.Event
The core advantage of building a Titanium app with Backbone is its powerful event system, and it couldn’t be easier to use. To mix in Backbone Events to an alloy controller, just add
Now that you have backbone events mixed in to your controller, you can start listing to and triggering them. First, let’s set up an event listener.
To break down that code snippet, using the ‘on’ function from underscore you can subscribe a function to be executed every time that some event is fired. Then, from whithin the other controller, you can use the ‘trigger’ function to notify listeners of some action. For example, if you had some picker controller, you could trigger a ‘change’ event whenever the user makes a new selection, and then listen for that event from the parent controller.
So why not normal callbacks?
Secondly, Backbone exposes a handful of functions that makes it very easy to clean up event listeners en masse. You can use ‘off’ to dismiss event listeners individually, dismiss listeners for an individual event, or tear down every event listener associated with a given object.
In addition to this system for managing events, the most recent version of Backbone provides a number of functions to allow objects to better manage their event listeners.
The advantage of using the listenTo pattern is that either object can tear down an event listener shared by them. This has important implications for Alloy controllers: as long as you manage most of your cross-controller interactions through Backbone.Events, you can tear down every event listener originating from a controller with a single call. We can use this feature to set up intelligent disposal functions that let us tear down most references to a controller quickly and prevent memory issues.
And that’s it. From here, you can set up other controllers to listen to the dispose event and do things like remove the controller when its disposed or build out new UI on controller disposal. Then, after all of the dispose listeners have been handled, all event relationships are automatically disposed of. Assuming you clean up all of your references in dispose events, there’s nothing else you need to do for the average controller to keep memory in check. Bear in mind that things like app-wide events (such as events on Titanium.App, Titanium.Geolocation, Titanium.Gesture, etc.) can still lead to memory leaks and should be handled in your disposal listeners.
You can read more about Backbone.js at the project’s website.
For more information about Backbone’s dependency Underscore and how you can use it to code better and faster, check out our blog post!
Memoize does exactly what the name says! It takes a function, and returns a version of it that will only calculate its return value once for a given set of inputs, and then cache this value and return it on subsequent calls. It’s absolutely great for functions that always give the same result but can take a long time to compute (the Fibonacci sequence is an oft-used example). For more information, Wikipedia has a great page on memoization.
Another great use would be for hash functions (e.g. the also-bundled-with-alloy sha1)
Underscore provides a awesome set of isSomething functions that can tell you all kinds of things about a given variable, ranging from its type to whether it is finite. Examples include isEmpty, isArguments, and isDate.
_.once and _.throttle are great for controlling frequency of execution of functions. Simply put, _.once makes it so a function can only be executed once, and _.throttle rate limits a function so that it can only be executed once every so often (e.g. at most once every 200 ms). Both are extraordinarily useful in the context of Titanium for dealing with issues associated with events getting created too quickly to be handled in a sensical fashion, such as a user tapping a button too quickly or scrolling too fast. Other awesome function processing functions include _.after (provided function is executed after being called a certain number of times), and _.debounce (function is only executed after it hasn’t been called for some period of time).
Underscore.js contains roughly 80 different commonly used functions for different purposes, too many for me to possibly go over here. Take a look at their docs, and feel free to leave comments about your favorites below!