Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Getting Started With MongoDB, Node.js, and Restify

DZone's Guide to

Getting Started With MongoDB, Node.js, and Restify

In this post, we’ll be covering how to set up a simple API with full CRUD operations using the ever-popular Restify framework backed by a MongoDB database.

· Database Zone
Free Resource

Learn how our document data model can map directly to how you program your app, and native database features like secondary indexes, geospatial and text search give you full access to your data. Brought to you in partnership with MongoDB.

With the multitudes of JavaScript frameworks available these days, there are countless options for building APIs. Many users can become overwhelmed and lose sight of the most important factors when it comes to building a REST API: speed, ease of use, and overall presence of the framework in the JavaScript community. In this post, we’ll be covering how to set up a simple API with full CRUD operations using the ever-popular Restify framework backed by a MongoDB database. For sake of simplicity, we’ll create a basic “to-do” style API.

Installing Node.js

Let’s get started by installing Node.js (if you already have Node.js installed, feel free to skip to the next section of this post). If you are on a Mac, the easiest way to install Node.js is via Homebrew, a package manager for macOS.

To do so, simply run the following command in your terminal and you’ll be ready to go: $ brew install node.

If you already have Node.js installed, make sure you’re running the latest version by running: $ brew upgrade node.

Once installed, you can run the following command to verify that node has been installed (please note that I’m currently running v7.10.0): $ node --version.

The output will display the latest version installed, which will be v7.10.0 or above: $ v7.10.0.

Note: If you’re on Windows or Linux, please read the installation instructions on the official Node.js website.

Getting Started With MongoDB Atlas

The easiest way to get started using MongoDB is with MongoDB Atlas, a managed service from MongoDB that facilitates seamless scaling and operations of your deployments in the cloud. It is super simple to set up and operate, and, best of all, there’s a free tier for small deployments – no credit card required.

To get started, head on over here and click the Start Free button.

From there, we’ll need to create a “group” to hold our free cluster. Feel free to name your group whatever you’d like. In this example, we'll work with a group called young-sea-3503.

Once your group is configured, you’ll be prompted to set up your first cluster. Simply follow the steps and choose the M0 instance size for the free tier. Once you deploy your instance, it should be available within about five minutes.

Create Our Application Directory

Let’s create a directory for our application. We will call it “rest-api”. To do so, simply run the following command in your terminal:

$ cd ~
$ mkdir rest-api && cd rest-api

Pro tip: The application directory location does not technically matter. I chose your root simply because it’s easy to find. Feel free to specify a different directory path if you’d like.

NPM Package Management

Now that Node.js is set up and we have a database to connect to, we’ll need to install the npm packages restify and mongodb (the official MongoDB driver for Node.js). When you installed Node.js, you also installed npm, which makes it super simple to install the necessary dependencies.

The best way to manage locally installed npm packages is to create a package.json file. A package.json file affords you a number of capabilities:

  • It documents which packages your project depends on.
  • It allows you to specify the versions of a package that your project can use, using semantic versioning rules.
  • It makes your build reproducible, which makes it way easier to share with other developers.

Installing the Necessary NPM Packages

Now that you understand the need for a package.json file, let’s run an npm command in your terminal to generate the file: $ npm init --yes

You should see the following output (the contents of your package.json file):

{
  "name": "rest-api",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Pro tip: Running the init command attempts to make reasonable guesses about how you want your options set and then writes a package.json file with the properties you select when prompted. If you invoke it with -f, --force, -y, or --yes, it will use only defaults and not prompt you for any options.

Now that we have the package.json file created, open up a terminal, navigate to the directory that contains your Node.js application and run the following command: $ npm install mongodb restify --save.

The command above will automatically install the mongodb and restify node modules from the npm registry.

Create a Configuration File

To keep things clean, I generally like to abstract important and/or reusable information into a configuration file. With that said, let’s create a file called config.js with the following command: $ touch config.js.

The contents of the file should look something like this:

'use strict'

module.exports = {
    name: 'rest-api',
    version: '0.0.1',
    env: process.env.NODE_ENV || 'development',
    port: process.env.PORT || 3000,
    db: {
        uri: 'YOUR_MONGODB_CONNECTION_STRING',
    }
}

With our config.js file in place, grab the connection string so we can add it to your configuration file. To do so, head back over to the MongoDB Atlas console and click on the Connect button. Once clicked, you will be presented with the following screen containing your connection string to your MongoDB Atlas cluster:

Connect for free

Click COPY and replace “YOUR_MONGODB_CONNECTION_STRING” in your config.js file with your provided connection string.

Here's an example of our config.js file with our MongoDB Atlas connection string specifying the API database using our username and password.

module.exports = {
    name: 'rest-api',
    version: '0.0.1',
    env: process.env.NODE_ENV || 'development',
    port: process.env.PORT || 3000,
    db: {
        uri: 'mongodb://$USERNAME:$PASSWORD@free-shard-00-00-example.mongodb.net:27017,free-shard-00-01-example.mongodb.net:27017,free-shard-00-02-example.mongodb.net:27017/api?ssl=true&replicaSet=free-shard-0&authSource=admin'
    }
}

Note: You will need to manually drop in the password you created when you initially built your cluster. For security purposes, the password is not visible in the console. Additionally, it’s best to also specify a user with read, write, or read and write access (depending on your needs). For the purpose of this tutorial, we have named the database api.

Whitelist Your IP Address

Because security is top of mind with MongoDB Atlas, we will need to whitelist our IP address in order to connect to the cluster. MongoDB Atlas makes this super simple by providing a button that says Add Current IP Address just above where you previously copied your connection string from.

Add current IP address

Create the Index.js File

The index.js file will serve as the main entry point to your Node.js API. To get started, let’s go ahead and create the file using the following command: $ touch index.js .

Next, let’s drop in some boilerplate code so that your application will kick off the Restify server process:

'use strict'

/**
 * Module Dependencies
 */
const config  = require('./config'),
      restify = require('restify'),
      mongodb = require('mongodb').MongoClient

/**
 * Initialize Server
 */
const server = restify.createServer({
    name    : config.name,
    version : config.version
})

/**
 * Bundled Plugins (http://restify.com/#bundled-plugins)
 */
server.use(restify.jsonBodyParser({ mapParams: true }))
server.use(restify.acceptParser(server.acceptable))
server.use(restify.queryParser({ mapParams: true }))
server.use(restify.fullResponse())

/**
 * Lift Server, Connect to DB & Require Route File
 */
server.listen(config.port, () => {

    // establish connection to mongodb atlas
    mongodb.connect(config.db.uri, (err, db) => {

        if (err) {
            console.log('An error occurred while attempting to connect to MongoDB', err)
            process.exit(1)
        }

        console.log(
            '%s v%s ready to accept connections on port %s in %s environment.',
            server.name,
            config.version,
            config.port,
            config.env
        )

        require('./routes')({ db, server })

    })

})

Setting Up Routes

Next, let’s create our routes for CRUD operations. With a fully fledged application, you would generally have dozens of route files; however, for our case, we’ll keep it simple and only have one route file called routes.js.

Let’s create our file by running the following command from your terminal: $ touch routes.js .

Now that you’ve successfully created your routes file, let’s start populating the file with your actual endpoints!

Below is boilerplate code to drop into your routes.js file (all of which is commented and should be self-explanatory):

'use strict'

module.exports = function(ctx) {

    // extract context from passed in object
    const db     = ctx.db,
          server = ctx.server

    // assign collection to variable for further use
    const collection = db.collection('todos')

    /**
     * Create
     */
    server.post('/todos', (req, res, next) => {

        // extract data from body and add timestamps
        const data = Object.assign({}, req.body, {
            created: new Date(),
            updated: new Date()
        })

        // insert one object into todos collection
        collection.insertOne(data)
            .then(doc => res.send(200, doc.ops[0]))
            .catch(err => res.send(500, err))

        next()

    })

    /**
     * Read
     */
    server.get('/todos', (req, res, next) => {

        let limit = parseInt(req.query.limit, 10) || 10, // default limit to 10 docs
            skip  = parseInt(req.query.skip, 10) || 0, // default skip to 0 docs
            query = req.query || {}

        // remove skip and limit from query to avoid false querying
        delete query.skip
        delete query.limit

        // find todos and convert to array (with optional query, skip and limit)
        collection.find(query).skip(skip).limit(limit).toArray()
            .then(docs => res.send(200, docs))
            .catch(err => res.send(500, err))

        next()

    })

    /**
     * Update
     */
    server.put('/todos/:id', (req, res, next) => {

        // extract data from body and add timestamps
        const data = Object.assign({}, req.body, {
            updated: new Date()
        })

        // build out findOneAndUpdate variables to keep things organized
        let query = { _id: req.params.id },
            body  = { $set: data },
            opts  = {
                returnOriginal: false,
                upsert: true
            }

        // find and update document based on passed in id (via route)
        collection.findOneAndUpdate(query, body, opts)
            .then(doc => res.send(204))
            .catch(err => res.send(500, err))

        next()

    })

    /**
     * Delete
     */
    server.del('/todos/:id', (req, res, next) => {

        // remove one document based on passed in id (via route)
        collection.findOneAndDelete({ _id: req.params.id })
            .then(doc => res.send(204))
            .catch(err => res.send(500, err))

        next()

    })

}

Verifying Our API Functionality With Postman

At its core, Postman is a powerful GUI platform built to make your API development faster and easier — from building API requests to testing, documenting, and sharing with teammates. It’s one of my favorite tools (and should be yours, too).

Start the server. In the root directory where your index.js file lives, simply type the following command: $ node index.js .

This will kick off the Node.js process and start your server on port 3000 (as defined in our config.js file) on localhost (http://localhost:3000). If all goes well, you should see the following output in your console:

rest-api v0.0.1 ready to accept connections on port 3000 in development environment.

To ensure that our API properly accepts the request, we’ll need to confirm that the Content-Type header is set to application/json.

Now that we have that set, let’s go ahead and create a document in our MongoDB “todos” collection in the api database by hitting the /todos endpoint with a POST request and a JSON body from Postman.

Choose the “raw” body type and JSON (application/json) from the ddrop-downmenu. By doing so, you’ll be able to construct your JSON much easier within Postman.

Copy the following snippet and paste it into the “raw” section to be passed along as your JSON payload:

{
    "name": "Nick",
    "task": "Make Moves",
    "status": "pending"
}

Inspect payload

If you inspect the payload, you’ll notice that the MongoDB driver automatically inserted an ObjectID (_id). More the MongoDB ObjectID can be found here. Additionally, our created and updated dates were automatically added to the document by the code we wrote.

Next, we can GET all of the documents via the /todos endpoint. If you looked at the GET function, you probably noticed logic for querying and limiting results. This works well because Restify automatically converts query parameters to JSON, allowing us to simply pass in the object as our MongoDB query. The payload response will contain the following:

Payload resonse

Let’s go ahead and update our task from “Pending” to “Complete” using the PUT HTTP method. This is similar to our HTTP POST, however, this time we’ll be using a different method and modified payload. We will also be passing the MongoDB ObjectID as a URL parameter:

Update task to complte

Note: Your body should consist of the following to ensure that the status is modified:

{
    "status": "complete"
}

Finally, let’s delete our document with the DELETE HTTP method (you’ll need to pass the auto-generated ObjectId from your initial call in the URL):

Delete document

You now have four functional API endpoints to power a todo list in which you can run full CRUD operations. While we covered just the tip of the iceberg, you are well along your way to adding additional functionality using the API/structural patterns provided in this tutorial.

Pro tip: You can kill your Node.js process at any time by pressing Ctrl + C.

Discover when your data grows or your application performance demands increase, MongoDB Atlas allows you to scale out your deployment with an automated sharding process that ensures zero application downtime. Brought to you in partnership with MongoDB.

Topics:
node.js ,mongodb ,crud ,api ,restify ,database ,tutorial

Published at DZone with permission of Nick Parsons. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}