Hints for adding mongodb to your RESTful Node.js service

In this lab, you will create a comments feature for your application. This feature should provide both GET and POST interfaces to your RESTFUL service.

The HTTP verbs comprise a major portion of the "uniform interface" constraints to a REST service. The primary or most-commonly-used HTTP verbs (or methods, as they are properly called) are POST, GET, PUT, and DELETE. These correspond to create, read, update, and delete (or CRUD) operations, respectively.

You will implement a POST on your "http://yourserver.org/comments" REST service for "create" to write a comment to the database, and GET for "read" to read all of the comments from the database. The following steps may help you in implementing your node.js service utilizing express and mongodb.
First, create a new express application using:

express comments cd comments npm install Now npm start will begin running your server that is pre set up to handle static files.

Get mongodb working on your hosting service. If you are using the bitnami image, you just need to change the authentication settings for mongodb as shown here:

  1. First stop the mongo daemon
    sudo /opt/bitnami/ctlscript.sh stop mongodb
    
  2. Edit the configuration file to turn off authentication
    sudo nano /home/bitnami/stack/mongodb/mongodb.conf
    
    Change the lines:
    #noauth = true
    auth = true
    
    to
    noauth = true
    #auth = true
    
    and save the file.
  3. Start the mongo daemon
    sudo /opt/bitnami/ctlscript.sh start mongodb
    

If you are using an EC2 image other than bitnami, or another hosting service, you should follow these steps.(You dont need to do this if you are on bitnami)

  1. Install mongodb. This process is covered in chapter 12 of the textbook. I suggest that you use version 2.4.8 since this is the version used in the book. cd /usr/local/src sudo curl -O http://downloads.mongodb.org/linux/mongodb-linux-x86_64-2.4.8.tgz sudo tar -zxvf mongodb-linux-x86_64-2.4.8.tgz cd mongodb-linux-x86_64-2.4.8 sudo cp bin/* /usr/local/bin sudo mkdir /data sudo mkdir /data/db sudo nohup mongod --fork --logpath /var/log/mongodb.log This will start mongod in the background so you can connect to it anytime you are on the machine. You will have to kill it manually if you want it to stop. It will create database files in the default directory "/data/db".

Bitnami users should pick back up here

Chapter 12 in the text will show you how to configure your database and to set up users. Start on page 216 to see how to control access to your database.

Now install the node modules that will allow you to connect to mongo

sudo npm install -g mongoose You could also get the package.json file. It will have all of the npm packages needed for all exercises in the book. Then run "npm update" to install all of those packages.
  • For this lab we will be creating and saving comments, so lets start with creating our index.html inside our "/public" folder. We would like to send a javascript object to our node.js service that has the following form: {"Name":"Mickey","Comment":"Hello"} So, lets build this object in a new jquery index.html file and make sure it is formatted correctly before we call our node service. <!DOCTYPE html> <html> <head> <title>Comments!</title> <script src="https://code.jquery.com/jquery-1.10.2.js"></script> <script src="javascripts/comments.js"></script> </head> <body> <form id="commentForm" action=""> <label for="name">Name: </label><input type="text" id="Name" placeholder="Name"><br> <label for="comment">comment: </label><input type="text" id="Comment" placeholder="Comment"><br> </form> <button id="serialize">Serialize form values</button> <button id="getThem">Get Comments</button> <div id="json"></div> <div id="done"></div> <div id="comments"></div> </body> </html> Next you'll need to create your comments.js file inside the "/javascripts" folder. $(document).ready(function(){ $("#serialize").click(function(){ var myobj = {Name:$("#Name").val(),Comment:$("#Comment").val()}; jobj = JSON.stringify(myobj); $("#json").text(jobj); }); }); When the button is clicked, the callback anonymous function will grab the form values, convert them to a JSON string and write them to the "json" div.

    Try your jquery html out on your static web server running on your EC2 instance and make sure the #json div has the correct JSON string.

  • Now lets build the REST service for POST (create in the "crud" vernacular). We'll start with making a route for the comment REST service in "routes/index.js". It should currently look something like this: var express = require('express'); var router = express.Router(); /* GET home page. */ router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); }); module.exports = router; So, go ahead and delete the existing route (as it is irrelevant to this project), and then you'll want to create a POST route in its spot. It should look something like this to start: router.post('/comment', function(req, res, next) { console.log("POST comment route"); //[1] res.sendStatus(200); }); Verify that you see the "POST comment route" log in your ssh window when you access the url through curl:
    man curl
     -d, --data 
                  (HTTP)  Sends  the  specified data in a POST request to the HTTP
                  server, in the same way that a browser  does  when  a  user  has
                  filled  in an HTML form and presses the submit button. This will
                  cause curl to pass the data to the server using the content-type
                  application/x-www-form-urlencoded. 
    
    You will have to use curl to generate a POST request. curl --data '{"Name":"Mickey","Comment":"Hello"}' http://localhost:3000/comment Make sure you see the "POST comment route" message in the window where you are running node.
  • Now lets see if we can generate that same HTTP POST request through your jquery html. Fortunately, it is really easy to do this with jquery, so add the following to your comments.js inside the function run with the "serialize" button. var url = "comment"; $.ajax({ url:url, type: "POST", data: jobj, contentType: "application/json; charset=utf-8", success: function(data,textStatus) { $("#done").html(textStatus); } }) Check to make sure you get to your POST route.
  • Now we need to interpret this data on the back end node service. Due to using express, which has a middleware called body parser, the data will come in one giant block, and we'll need to pick the pieces out that we need. First, check to make sure the request contains what you want by adding the following line to your POST route (before the sendStatus line): console.log(req.body); //[2] Once you've confirmed that it does have the correct data, utilize the following line to create a new Comment: Finally, now that we know the comment we've made is correct, we can save it to our database. This takes two steps. First, we need to connect to the database using mongoose (which we installed earlier). Add the following to your routes/index.js file. /* Set up mongoose in order to connect to mongo database */ var mongoose = require('mongoose'); //Adds mongoose as a usable dependency mongoose.connect('mongodb://localhost/commentDB'); //Connects to a mongo database called "commentDB" var commentSchema = mongoose.Schema({ //Defines the Schema for this database Name: String, Comment: String }); var Comment = mongoose.model('Comment', commentSchema); //Makes an object from that schema as a model var db = mongoose.connection; //Saves the connection as a variable to use db.on('error', console.error.bind(console, 'connection error:')); //Checks for connection errors db.once('open', function() { //Lets us know when we're connected console.log('Connected'); });
  • Now you need to put the data from the browser into the database, by adding this to your post route (make sure you take out the old sendStatus) var newcomment = new Comment(req.body); //[3] console.log(newcomment); //[3] newcomment.save(function(err, post) { //[4] if (err) return console.error(err); console.log(post); res.sendStatus(200); });
  • Check to see that mongodb has been updated correctly (This is described in the book starting at page 220 and Figure 12.7).
    You Type Mongo Response
    sudo mongo MongoDB shell version: x.x.x
    connecting to: test
    show dbs [List of DBs]
    use commentDB switched to db commentDB
    show collections comments
    system.indexes
    coll = db.getCollection("comments") weather.comments
    coll.find() { "Name" : "Mickey", "Comment" : "Hello", "_id" : ObjectId("54f53d5ebf89e6100c2180da") }

  • Since we didnt give mongoose a name for the collection, it pluralized the schema name and we get the collection comments.
  • At this point you have the POST (create in CRUD) part of your REST service complete. You now need to implement the GET (read in CRUD). First install the route in your routes/index.js file. /* GET comments from database */ router.get('/comment', function(req, res, next) { console.log("In the GET route"); }); And make sure you can see this log printed out when you go to http://[yourserverip]/comment
  • Now you need to connect to mongo and read the database entries, so adjust your route to look as follows: /* GET comments from database */ router.get('/comment', function(req, res, next) { console.log("In the GET route?"); Comment.find(function(err,commentList) { //Calls the find() method on your database if (err) return console.error(err); //If there's an error, print it out else { console.log(commentList); //Otherwise console log the comments you found } }) }); There are more optional parameters to the find function that you could specify to get a subset of the database.
  • Now that you have the database collection on the server side, you need to send it back to the browser. res.json(commentList); //Then send them You should be able to test your REST service by entering the url http://yourserverip/comments into your browser
  • Now we want to add the jquery code to access this GET part of our REST service. $("#getThem").click(function() { $.getJSON('comment', function(data) { console.log(data); var everything = "<ul>"; for(var comment in data) { com = data[comment]; everything += "<li>Name: " + com.Name + " -- Comment: " + com.Comment + "</li>"; } everything += "</ul>"; $("#comments").html(everything); }) }) Test to make sure you can insert comments using your REST POST route and get the result back using your REST GET route. I hope you realize the power of having a javascript object that can be passed directly to your node.js REST service that can be placed directly into the mongo database. You can then directly grab the document object out of the database and pass it back to your javascript front end. We didnt cover queries, but you conduct queries by creating an object that is passed to the query interface of mongo.