Nodejs Restify MongoDB – Build your own REST API

Tweet about this on TwitterShare on LinkedIn3Share on Google+10Share on Reddit0Buffer this pageFlattr the authorEmail this to someonePrint this page

Nodejs Restify MongoDB – Build your own REST API

Nodejs Restify MongoDB tutorial

Restify GET PUT DELETE POST

MongoDB Mongojs MongoLab

Runnable Demo

In this post, we are going build a Node based REST API for a collection in our application. We will use Restify to handle our server endpoints. Then we use Mongojs to interact with the database. We will be using MongoLab, (a free* MongoDB as a Service) to store our data. To make things a bit more interesting, we will use Runnable to deploy the app and share it with the world.

We will be building a simple product API, where we Create a new product, Read the product, Update the product and finally Delete the product using the traditional REST methods POST, GET, PUT & DELETE.

The final output of this post would be

Screen Shot 2014-04-20 at 4.35.49 pmTo get your hands on the above demo, navigate to myRunnable, scroll to the very end of the page & wait for the terminal to show up. Then run

node client.js

to see the above output.

Contents

You can find the complete code hereNow, Let’s see how we can build the REST API.

What is a RESTful API?

REST is the underlying architectural principle of the web. The amazing thing about the web is the fact that clients (browsers) and servers can interact in complex ways without the client knowing anything beforehand about the server and the resources it hosts. The key constraint is that the server and client must both agree on the media used, which in the case of the web is HTML.

cont. on SO..

You can find another good tutorial on REST here.

We are going to use Node as our server to host our application locally. You can read more above node here & you can set up node from here.

Create a new folder named myRESTAPI. Open terminal/prompt here and lets create a new node project. Run

npm init

and fill it with your details

Screen Shot 2014-04-20 at 5.03.58 pmNext, we will create 2 new files inside the myRESTAPI folder. Name them server.js and client.js.

Now, we will install the project dependencies. The first dependency is Restify.

What is Restify?

Restify is a node.js module built specifically to enable you to build correct REST web services. It intentionally borrows heavily from express as that is more or less the de facto API for writing web applications on top of node.js.

Restify takes most of its functionality from Expressjs.

Expressjs – Non-Restful stuff = Restify

You can know more about Restify here.

Our second dependency is Mongojs.

What is Mongojs?

Mongojs is a node.js module for mongodb, that emulates the official mongodb API as much as possible. It wraps mongodb-native and is available through npm

If you are new to MongoDB, you can download the latest copy of MongoDB from here to play around. But for this post, we are going to use MongoLab to manage our data.

If you are a beginner, MongoDB is a NoSQL database. Unlike MySQL or MSSQL or Oracle DBs, here database have collections instead of tables. We have documents in collections insteads of rows in a table. And best of all, all the documents are stored as JSON. You can know more about MongoDB here.

If you have never worked with MongoDB before, you can remember the following commands to navigate around and perform basic operation

Command Result
mongod  will start the MongoDB service
mongo  will step you inside the MongoDB shell (when run in a new tab, while Mongod is running)
show dbs  will show the list of databases
use <<database name>>  will step you inside the database
show collections  will show the list of collections once you are inside the database
db.collectionName.find()  will show all the documents in that collection
db.collectionName.findOne()  will show the first document
db.collectionName.find().pretty()  will pretty print the JSON data in console
db.collectionName.insert({key : value})  will insert a new record
db.collectionName.update({condition : value}, {$set : {key:value}}, {upsert : true})  will update a record with the given condition & sets the required value. If upsert is true a new document will be created if no documents with matching condition are found
db.collectionName.remove({})  will remove all the documents in that collection
db.collectionName.remove({key : value})  will remove the documents matching the condition

You can learn more about MongoDB here. And Mongojs here.

Now, we are well acquainted with our components. Lets add the dependencies to our project. Back to terminal/prompt run

npm i restify --save-dev

npm i mongojs --save-dev

This will install both our dependencies.

Setup MongoLab account

Navigate to MongoLab and sign up for a new account if you don’t have one, else login. Next, create a new database then fill the details as

Screen Shot 2014-04-20 at 5.29.21 pm

You can give a database name you like and click on create.

Then to access the database, we need to create a new user to access the database. From the home page, click on the database name and click on the user’s tab. Then create a new user. Remember the username and password.

To access the data remotely, we will build a connection string. On the database homepage, you will see a section on top of the page, Screen Shot 2014-04-20 at 5.34.38 pm

Fill in the placeholders in the above URL and you are done!! We will use this URL in just a moment.

Continue Development

Open server.js in your favorite editor. To get started with our project, we will first add the required dependencies.

Next, let’s create a new server and start it. Add the below lines to server.js

Finally, ask it start listening to any free port

Then back to prompt/terminal run

node server.js

And you should see the server started message. If you want you can open a browser and navigate to  http://localhost:3000 to see a message like

{"code":"ResourceNotFound","message":"/ does not exist"}

Because we have not yet created any end points.

GET – All Products

Lets create a new GET endpoint. Add the below code to our server.js

server.get()  method takes 2 arguments. One the endpoint to which it needs to listen to and the second argument is the callback function, which will be called when that endpoint is hit.

Restify server methods, like any Express middleware, provides 3 arguments to its callback method.

req – The request object, which contains all the data that comes from the client

res – The Response object, which contains all the data that the server sends to the client

next – The next method, which is used to invoke the next middleware method in queue.

If you want to write back anything to the client, you need to use  res.send();. Since we are dispatching a REST response, its our duty to dispatch the HTTP response code as well as the content header.

Back to terminal, kill the running node app by pressing ctrl + c and the restart it by running   node server.js . You may need to do this again and again when you make changes to the server.js. If you are lazy like me, you can install nodemon a node package for restarting the node app automatically when changes are made.

Windows Mac/*nix
npm i -g nodemon    sudo npm i -g nodemon

Now, run  nodemon server.js and then navigate to  http://localhost:3000/products, to see the newly updated message.

Now, lets add the db config to our server.js. Update the below URL with your db config.

var db = mongojs('mongodb://admin:[email protected]:53718/restifymyapp', ['products']);

If you are planning to user your local db instance, your connection string would be

var db = mongojs('productsdb', ['products']);

Where, productdb is the name of the database & products is the name of the collection.

And the updated server.js would be

Now, instead of spitting out a static message, lets hit the DB and dispatch a list of products. Our updated get method would be

You can navigate back to the browser and refresh the /products endpoint. And you should see an empty array, since we do not have any products yet.

POST – Add New Product

Now, lets add a POST method so that we can save a product. You can add the below POST method to server.js

As you can see, we are getting the product object from the req.params. This is sent by our client. You can use chrome extensions like Postman or Advanced REST client to perform the REST operations.

But, to get a complete understanding of Restify, we will leverage Restify’s JSONClient. Open client.js and add the below code.

Do notice Line no 2. Here we are referring to our server.js file. The reason behind this is, if we need to run the server and client, we need to run in 2 terminals, one for server and one for client. Instead, I am invoking the server.js from client.js so that the server starts and then using client.js, we will access the server.

Lines 21 to 29, the response is node style. i.e. they are all async. IMO, this is good for performance but bad for development. The callback will be fired when the server responds with either an error or the actual response.

Next, add the below line of code to server.js at the very end

module.exports = server; 

This is a node way of exporting stuff to be used in other files. You can learn more here.

Now, back to terminal/prompt, run

nodemon client.js

And you should see something like

Screen Shot 2014-04-20 at 6.37.38 pm

Our product has been inserted. yay!! Now, lets add a client method to fetch all the products

PS : If you save the file, remember that the POST will run again a new record will get saved and now we will see 2 products.Screen Shot 2014-04-20 at 6.41.14 pmIf you dont want this to happen, you can comment out the post part on the client.

PUT – Update an Existing Product

The PUT method is for updating an existing product, whereas POST is for saving a new product. The only key difference is that in PUT we know the object we are dealing with, whereas in POST we don’t. So, if you are ever stuck in making a decision between PUT & POST, all you need to do is answer the above question.

In PUT, we will be updating only the changed values, But since we are not aware of the changes on the server side, I am merging the existing object with the one I get from client. And I override the product on the server with the one from client.

I know, its very convoluted. If you know a better method, please do comment.

And our client to test the above code would be

Do notice on Line no 1, we are adding a new property named price before we send the data to the server. This is our test for checking if the update has actually worked.

If you save the files, nodemon will restart the server & client and you should see
Screen Shot 2014-04-20 at 6.53.52 pm

DELETE – Delete a Product

The Final HTTP method, where we send a Product ID to the server and the server will remove it from the DB using Mongojs API.

The server side code for DELETE method would be

And the client code would be

And the output would be

GET – Fetch One Product

Finally, we will create another GET method to fetch only one product based on the Product ID. The server side code would be

And the client would be

On the client.js, If you have commented out the POST method and ran the delete method, you will not have any records in DB. Uncomment POST, save and you should see

Screen Shot 2014-04-20 at 7.17.05 pm

Simple right?

Super Asynchronous Client

As you can see that our client is Async in nature. We can’t have 2 methods one after the other and expect to see the output in order of execution.

So, to test all the above server methods sequentially, add the below piece of code to client.js

Yeah.. Super Async!! You can see the output in the console. All the methods running one after the other.

You can find the complete code here.

Deploy to Runnable

I have recently come across Runnable.com and they are amazing!!. You can create runnables that execute in a certain environment like node and the share the results with your team.

You can create a new account with them, which is free (duh!). Then you can create a new runnable or you can upload your code to GitHub and give that link. Runnable will do the rest to make it runnable.

I have deployed the above code to runnable here. You can check it out. Also do check out their other environments on Runnable.com too.

Hope you got an understanding of REST API and how you can create your own using Nodejs and Restify.


Thanks for reading! Do comment.
@arvindr21

Tweet about this on TwitterShare on LinkedIn3Share on Google+10Share on Reddit0Buffer this pageFlattr the authorEmail this to someonePrint this page
  • Edouard Jubert

    Hi everyone, and thank you so much, this tutorial is really helping.
    But after following all the steps, I have an annoying issue as you can see on the first screenshot (maybe due to MongoLab because as you can see on the second screenshot, I cannot even ask a ‘show dbs’ on terminal after connecting successfully)
    Does anyone ever experience this problem and succeed to correct it?

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      you will not have permission to run this command on mlab. Try

  • Jim Hlad

    Great post… you’ve given me lots of new ideas for a course I’ve made on the same topic.

    Also very interesting domain name :-)

    Jim
    Instructor | https://www.udemy.com/a-simple-nodejs-api/

  • Anonymouse

    Thanks a lot! Real simple and easy to start with.

  • aniket bansode

    hey nic post but can u also share how to insert ,update,delete and search through advance rest client or postman using existing server.js

  • whoever

    Although it has some outdated file which blocks me to follow the tutorial,but I finally solve it,it works thanks.

    If you get problem to have the working project,here’s a quick setup
    1. In terminal, git clone https://github.com/arvindr21/restify-mongojs-app
    2. In package.json,edit the version mongojs from
    ^0.12.1 to ^2.3.0
    or lastest version,otherwise you will get
    Failed to load c++ bson extension, using pure JS version
    3. In terminal, npm install –no-optional
    Otherwise you will get something like
    Error: Cannot find module ‘./build/Release/DTraceProviderBindings
    4. node server.js,and shows Server started @ 3000
    This should work,hope it helps

  • Jaden Ng

    Hi Arvind,

    I encountered some issues with the following code,

    • Jaden Ng

      Hi Arvind,

      I encountered some issues with the server.get code that invoke the “db”. I always got the error complaining internal error 500 as shown in picture below. Could you advise.Thanks :)

      • Jaden Ng

        The output I got when I tried to do console.log(db);

        • Jaden Ng

          I guess this like is having problem.

          db.products.save(product,

          function (err, data) {

          console.log(“HELP”);

          res.writeHead(200, {

          ‘Content-Type': ‘application/json; charset=utf-8′

          });

          res.end(JSON.stringify(data));

          });

  • Guilherme Freire

    Hi Arvind. I’m having a problem which can’t seem to find out. I’m new with all this. I replicated your code and the client post does not show any item saved. I says that it was saved, but there is nothing inside the brackets {}. My output: Server started @ 3000
    Product saved >>>>>>>
    {}

    Am I missing something?

  • Steven Guang

    When I try to update a product, I got a ResourceNotFoundError : product/1 does not exist.
    What did I do wrong ? I’m kind of new to this. Thank in advance

  • Bert Vriens

    Very good article as are all I’ve read here 😉
    Tip for people building a restfull api : if you want to speed up the development of an restfull api with mongo and node, google node-restfull. Does a lot of repetitive work for you.

  • Isaac Bhasme

    Thank you very much. All your tutorials are very helpful.
    By the way, the section on “updating an existing product”; you are doing a db read and overwriting the attributes with the object attributes passed from client.js. I was trying the following to avoid the read and just do an update.

    server.put(‘/product/:id’, function (request, response, next){
    db.products.update(
    {id: request.params.id},
    {$set: request.params },
    function (error, data){
    response.writeHead(200, {‘Content-Type’ : ‘application/json; charset=utf-8′});
    response.end(JSON.stringify(data));
    });
    return next();
    });

    It seems to work, but I’m not sure whether I’ve introduced any new issues by doing this.
    Let me know what you think.

  • http://twitter.com/benjaminmbrown Benjamin M. Brown

    Runnable seems to be invite-only now.

  • Tiger

    It throws following error when I try to insert records:

    An error ocurred >>>>>>

    { [MethodNotAllowedError: POST is not allowed]

    message: ‘POST is not allowed’,

    statusCode: 405,

    body:

    { code: ‘MethodNotAllowedError’,

    message: ‘POST is not allowed’ },

    restCode: ‘MethodNotAllowedError’,

    name: ‘MethodNotAllowedError’ }

    Do I need to make any change?

  • Roberta Coeli

    Thank you so much! It has helped me a lot.

    And congrats for the website.

  • Cyiza Rwanda

    Thank you so much. There has been more on MongoDB… Can you at a time of your choice talk about Apache Cassandra? Thank you so much….

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hello Cyiza, thanks! Sure, may I ask, what kind of apps are you planning to do with Cassandra over MongoDB?

  • William Wambua

    I like this tutorial.Helped me understand REST using node and MongoDb.
    Thank you.

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Glad I could be of help. Thanks!

  • Majid Lotfi

    Hi, Thank you for this tutorial,

    Is there any way to integrate it with a client that has forms and tables, like angularjs ?
    thanks

  • vrcat

    can you please also talk about REST API versionning?

  • vrcat

    Hi, I tried your tutorial to update the product by adding an attribute price=100USD. As I kept running the client.js a few times, there became four duplicate product records and all with id:1.
    I thought running PUT from the client will update all four product records by adding attribute price=100USD, but the result was only the first record had the new attribute Price=100USD.

    Why is that? Thanks.

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hello vrcat, if you see the logic for PUT request we have used

      This will always fetch the first matching object in the collection. And then we update only that. That is why only the first product is updated. In an ideal scenario, a collection will and should not have multiple entries with same id. So, this situation, you mentioned will not arise.

      Thanks.

      • vrcat

        thanks very much for reply. it was helpful. I do have another question though, what’s the best way to make the client side more interactive? e.g. the user can choose an action, add one first, delete another one, update one, etc. Because the current client.js does the actions in a sequence, which is not very user friendly. Do you have a tutorial/suggestion? Thank you.

      • vrcat

        sorry, one more question: how can I deploy it to an application server, e.g. websphere, ? thank you

        • http://thejackalofjavascript.com/ Arvind Ravulavaru

          Nodejs is the application server where your app is deployed to. When you run nodemon server.js that is where you are deploying your code to the nodejs server.

  • acveer

    Great Tutorial. Well written.

    I wanted to run the Async code in a for loop for testing/learning purposes. (repeat end to end 2 times). The JS for loop does not work as it executes next iteration, before the last iteration finishes. Could you point me in the right direction. Thank you,

    Total products : 0
    ————————————
    Total products : 0
    ————————————
    Inserted product : 54b2aaf8e59d9d202d6c7ee0
    —————————————–
    Inserted product : 54b2aaf8e59d9d202d6c7ee1

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hello acveer. Thanks!

      I did not quite get your requirement. You want to iterate the client async code 2 times in a row without the callback hell?

      Thanks.

  • Shalin Luo

    Really nice!! This is the best start tutorial I’ve seen till now! Thanks a lot!!

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Thanks Shalin!

  • http://ericdouglas.github.io/ Eric Douglas

    Arvind, could I translate some of your articles?

    Thanks in advance!

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Thanks for the offer Eric. You can surely do so. Please do share the translated links so that I can link them to the posts. –Thanks.

  • Mark Chiles

    Arvind hope you are doing well. I was looking to potentially use part of this and part of the API from the end to end hybrid app. One thing I was working on was extending the /data/list component to show lists of tasks below a specific ID. For instance, multiple top level tasks could have sub tasks. The sub tasks would be associated to the top level task by it’s ObjectId. Was thinking something like /data/list/:id but that seems to not quite work. Thoughts?

    Thanks, Mark

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Hello Mark. I am good. Thanks! Hope you are doing well too.

      Coming to the task at hand, you would need to create a new collection that will store the list of sub-tasks for a task.

      Example :
      Collection – lists

      Collection : listItems

      And once you have a structure like this, you can use /data/lists/:id <– will return one item. If you want sub-items then you need to build a endpoint like /data/listitems/:id <– the id here will be the list id. And in our listitems collection, you will query for listid and return the array back.

      Makes sense?

      Thanks.

      • Mark Chiles

        Thanks, Arvind. I was on the right track. I sent you a message on LinkedIn.

        • Mark Chiles

          Did you get my inquiry on LinkedIn? Thanks, Mark

          • http://thejackalofjavascript.com/ Arvind Ravulavaru

            @markchiles:disqus Replied to your inquiry. Thanks.

  • ImINaBAR

    Awesome, my first real experience with nodejs beyond gulp, and I like it. Object manipulation is fantastic this way.
    I’m off to the Ionic end to end app tutorial you wrote.
    Thanks!

    • http://thejackalofjavascript.com/ Arvind Ravulavaru

      Glad to hear that ImINaBAR!. Thanks.