I recently read the article on Scotch.io regarding using Mongoose and MongoDB. I thought to myself, hey, Couchbase can do the same thing if you use Ottoman instead of Mongoose.
This article is going to walk through the same comparisons as the Scotch.io article, but use Ottoman and Couchbase instead of Mongoose and MongoDB.
What is Ottoman
Ottoman, for Couchbase, is an object document mapper (ODM) that allows you build what your object model would look like, then auto-generate all the boilerplate logic that goes with it.
Ottoman us to easily access CRUD commands for Couchbase Server using Node.js. To use Ottoman, make sure you add it to your Node.js project by using the following command:
1 2 3 |
npm install ottoman --save |
Now that the libraries have been downloaded to our project, we need to include it in our source code. This can be done by adding the following to one of your JavaScript files:
1 2 3 |
var ottoman = require("ottoman"); |
With the Ottoman libraries included in the project we need to now give Ottoman access to one of our buckets.
1 2 3 |
ottoman.bucket = (new couchbase.Cluster("http://localhost:8091")).openBucket("bucket-name-here"); |
If you’ve used the Node.js SDK for Couchbase before, the above will look familiar to you. We’re just connecting to a cluster, opening a bucket, and then assigning it to Ottoman.
At this point we can start using Ottoman to accelerate our development process.
Defining a Model
Before we can start doing CRUD operations against Couchbase, we need to define our Ottoman model. These models represent documents in our database.
The models we create with Ottoman can have properties and methods. The methods part we’ll get to soon, but for now check out simple models with properties.
Sample Model for Users
Let’s take the following model for new users to our application (yes it is simple in this example).
1 2 3 4 5 6 7 8 |
var UserModel = ottoman.model("User", { firstname: {type: "string"}, lastname: {type: "string"}, email: {type: "string"}, created_at: {type: "Date", default: Date.now} }); |
We now have a model that can be used like so:
1 2 3 4 5 6 7 |
var myUser = new UserModel({ firstname: "Nic", lastname: "Raboy", email: "test@example.com" }); |
We set the first name, last name, and email, but we don’t have to set the created_at value. This is because by default, if we don’t set it, it will be set as the current timestamp.
Custom Methods
Let’s say we want to have a method do a consistent task within our model. Take the following for example, assuming we’ve already created our simple UserModel object.
1 2 3 4 5 |
UserModel.prototype.printWhoDaBoss = function() { console.log(this.firstname + " " + this.lastname + " is Da Boss"); } |
In theory, this would print out the first and last name of a particular Ottoman model.
Sample Usage for Custom Methods
To use a custom method, we can use the printWhoDaBoss as seen previously and do something like this:
1 2 3 4 5 6 7 8 9 |
var myUser = new UserModel({ firstname: "Nic", lastname: "Raboy", email: "test@example.com" }); myUser.printWhoDaBoss(); |
The above would print out Nic Raboy is Da Boss. Of course that particular function is useless, but you can use your imagination to build something better with the concept.
Running a Function Before Saving
What if we want to execute a task before a document gets saved into Couchbase? This can be accomplished using the pre reserved method that ships with Ottoman. For example, let’s say we want to alter everyone’s last name before they are saved:
1 2 3 4 5 6 |
UserModel.pre("save", function(next) { this.lastname = "da Boss " + this.lastname; next(); }); |
Now when someone tries to save a document, which will be demonstrated in the next section, their lastname will be prefixed. For example Raboy would become da Boss Raboy. Not particularly useful in this case, but you should get the idea.
Creating a Document
To create documents we need to make use of the built in save method of Ottoman. With our model, we can do something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var myUser = new UserModel({ firstname: "Nic", lastname: "Raboy", email: "test@example.com" }); myUser.save(function(error) { if(error) { console.log("An error happened -> " + JSON.stringify(error)); } console.log("Save successful!"); }); |
A key would be generated and the document then saved into the database.
Reading NoSQL Documents
Reading documents with Ottoman is a little different because there are different types of reads we can do. Let’s break down a few usage scenarios.
Finding All Documents
It is often difficult in NoSQL to get documents when you don’t know the document id. Without creating a view or using Couchbase’s N1QL technology, you would be pretty much out of luck. Here is an alternative.
1 2 3 4 5 6 7 8 |
UserModel.find({}, function(error, result) { if(error) { console.log("An error happened -> " + JSON.stringify(error)); } // Do something with the resulting Ottoman models }); |
The above would find all documents that were created using the Ottoman UserModel.
Finding a Specific Document
Here is another scenario. Let’s say you don’t want every document and you don’t know the document id. You can do a query with Ottoman by expanding upon the find command.
1 2 3 4 5 6 7 8 |
UserModel.find({lastname: "Raboy"}, function(error, result) { if(error) { console.log("An error happened -> " + JSON.stringify(error)); } // Do something with the resulting Ottoman model }); |
Find a Document by ID
Let’s say you know the id of the document that you want. You can grab the Ottoman model by running:
1 2 3 4 5 6 7 8 |
UserModel.getById("document-id-here", function(error, result) { if(error) { console.log("An error happened -> " + JSON.stringify(error)); } // Do something with the resulting Ottoman model }); |
This is similar to just using the get method of the Node.js SDK, however, instead of JSON data that you’re left with, you instead have a fully functional Ottoman model.
Updating an Existing Document
Updating documents with Ottoman can be a little tricky because you must first have loaded the document before trying to do a manipulation on it. What you could do is find the particular document by id, then perform the save command like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
UserModel.getById("document-id-here", function(error, result) { if(error) { console.log("An error happened -> " + JSON.stringify(error)); } result.firstname = "Nicolas", result.save(function(error) { if(error) { console.log("An error happened -> " + JSON.stringify(error)); } }); }); |
In the above example I would have first obtained my particular model, changed only the first name of it, then called save. The save command will create or update, but it is up to you to lead up to that point.
Removing a Document
Deleting a document will work in a similar sense to updating a document with Ottoman. First you must load the document by doing a lookup, then by calling the remove function. A simple example of this can be seen below:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
UserModel.getById("document-id-here", function(error, result) { if(error) { console.log("An error happened -> " + JSON.stringify(error)); } result.remove(function(error) { if(error) { console.log("An error happened -> " + JSON.stringify(error)); } console.log("Document was removed!"); }); }); |
Conclusion
Ottoman is a great ODM tool for Couchbase that models our objects and plays nicely for CRUD type operations. Mongoose for MongoDB tries to be like Ottoman as demonstrated in the article on Scotch.io regarding Mongoose and MongoDB. This article was intended to show how Ottoman is just as easy, if not easier to use.