Description

Mongoose Basics is an ORM for MongoDB.

NOTE: There is an Angular, React and jquery version of this assignment. Make sure you are looking at the right one. This is the React assignment, the others are called AngularMongooseBasics and MongooseBasics.

Before proceeding, be sure you have an account on https://mlab.com/.

Put your address-list.json in the public directory.

Step Three

Download empty lubuntu:

Step Four

Set up and learn a little about Mongoose. Mongoose is probably the most popular way to access MongoDb from Node Js applications. Other popular options include Monk and the native drivers, which are called MongoDb. Mongoose relies on MongoDb.

First install mongoose:

npm install mongoose --save

In the past, you might have seen messages about mongoose, C++ and bson. They should no longer occur, but if you are encountering them, see the Elvenware notes on this subject.

NOTE: On Linux, you may need to install libkrb5-dev before you can install the Mongoose NPM package. This should not be an issue on Cloud 9.

sudo apt-get install libkrb5-dev

The Mongoose Schema

Once Mongoose is installed, you should set up a schema:

  • Create a folder called models at the root of your project
  • Put this code in a file called models/politicians.js:
var mongoose = require('mongoose');

var politicianSchema = mongoose.Schema({
    'firstName': String,
    'lastName': String,
});

module.exports = mongoose.model('politician', politicianSchema);

Go ahead and fill in the rest of the fields according to the structure for your data. The fields will probably all be of type String.

In routes/index.js add these two things to the existing code:

var allMongo = require('./all-mongo');
var connect = require('./connect');

router.get('/', function(req, res, next) {
    'use strict';
    res.render('index', {title: 'CongressServer'});
});

router.get('/bar', function(request, response) {
    response.status(200).send({result: 'bar'});
});

router.get('/:id', function(request, response) {
    'use strict';
    response.status(200).send({ result: request.params.id });
});

Later we will add methods methods to open your collection.

In index.js, make sure that this is the last line in the file:

module.exports = router;

Connecting

Here is a tool for connecting to the database. It belongs in its own file called routes/connect.js:

/**
 * Created by charlie on 6/6/16.
 */

const mongoose = require('mongoose');

const connect = {

    connected: false,

    simpleConnect: function() {
        'use strict';
        console.log('Connecting with simple.');
        const url = 'mongodb://127.0.0.1:27017/test';
        console.log(url);
        connect.connected = true;
        mongoose.connect(url);
        const db = mongoose.connection;
        db.on('error', console.error.bind(console, 'connection error:'));
        db.once('open', function(callback) {
            connect.connected = true;
            console.log('Opened connection to mongo');
        });
    },

    custom: function() {
        'use strict';
        console.log('Connecting with simple.');
        //const url = 'mongodb://127.0.0.1:27017/test';
        const userName = 'charlie';
        const password = 'foobar';
        const siteAndPort = '192.168.2.18:27017';
        const databaseName = 'test';
        const url = 'mongodb://' + userName + ':' + password + '@' + siteAndPort + '/' + databaseName;
        console.log(url);
        connect.connected = true;
        mongoose.connect(url);
        const db = mongoose.connection;
        db.on('error', console.error.bind(console, 'connection error:'));
        db.once('open', function(callback) {
            connect.connected = true;
            console.log('Opened connection to mongo');
        });
    },

    // mongodb://<dbuser>:<dbpassword>@ds049848.mlab.com:49848/elvenlab01
    mlabConnect: function() {
        'use strict';
        console.log('Connecting with mlab.');
        connect.connected = true;
        var userName = 'pol';
        var password = 'polFooBarQux';
        var siteAndPort = 'ds049848.mlab.com:49848';
        var databaseName = 'elvenlab01';
        var url = 'mongodb://' + userName + ':' + password + '@' + siteAndPort + '/' + databaseName;

        mongoose.connect(url);

        // This part is optional
        var db = mongoose.connection;
        db.on('error', console.error.bind(console, 'connection error:'));
        db.once('open', function(callback) {
            connect.connected = true;
            console.log('Opened connection to mongo');
        });
    },

    doConnection: function(option) {
        'use strict';
        if (typeof option === 'undefined') {
            option = 'simple';
        }

        switch (option) {
            case 'simple':
                connect.simpleConnect();
                break;
            case 'custom':
                connect.custom();
                break;
            case 'mlab':
                connect.mlabConnect();
                break;
            default:
                connect.simpleConnect();
        }
    }
};

module.exports = connect;

Step 5

Here is index.pug:

extends layout

block content
  h1= title
  p Welcome to #{title}

	button#insertValidData Insert Valid Data
	button#getAll Get All
	button#emptyCollection Empty Collection

  pre#display

and layout.pug

doctype html
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
    link(rel='stylesheet', href='/components/bootstrap/dist/css/bootstrap.css')
    script(src="components/jquery/dist/jquery.js")
    script(src="components/bootstrap/dist/js/bootstrap.js")
    script(src="javascripts/control.js")
  body
    block content

Step Six

Here is public/javascripts/control.js:

$(document).ready(function() { 'use strict';
    const insertUrl = '/insertValidCollection';
		let collection;

    function insertCollection() {
        var jqxhr = $.get(insertUrl, function(result) {
            alert( "success" );
            console.log(JSON.stringify(result, null, 4));
        })
            .done(function() {
                console.log( "second success" );
            })
            .fail(function() {
                alert( "error" );
            })
            .always(function() {
                console.log( "finished" );
            });
    }    

		function getAll() {
        $.getJSON('/all-data', function(result) {
            collection = result.allData;
            $('#display').html(JSON.stringify(result, null, 4));
        })
            .done(function() {
                console.log('second success');
            })
            .fail(function(error) {
                alert(JSON.stringify(error.responseJSON, null, 4));
            })
            .always(function() {
                console.log('finished');
            });
    }

		function emptyCollection() {
        $.getJSON('/emptyCollection', function(result) {
            $('#display').html(JSON.stringify(result, null, 4));
        })
            .done(function() {
                console.log('second success');
            })
            .fail(function() {
                alert(JSON.stringify(a.responseJSON, null, 4));
            })
            .always(function() {
                console.log('finished');
            });
    }

    function update() {
			collection[0].firstName = 'foo';
			const newData = {
					id: collection[0]._id,
					firstName: collection[0].firstName
			};
			$.getJSON('/update', newData, function(result) {
            $('#display').html(JSON.stringify(result, null, 4));
        })
            .done(function() {
                console.log('second success');
            })
            .fail(function() {
                alert(JSON.stringify(a.responseJSON, null, 4));
            })
            .always(function() {
                console.log('finished');
            });
    }

		$('#insertValidData').click(insertCollection);
		$('#getAll').click(getAll);
		$('#emptyCollection').click(emptyCollection);
		$('#update').click(update);
});


Step Seven

In routes/index.js append all of the following before the module statement:

var express = require('express');
var router = express.Router();
var connect = require('./connect');
//var politicians = require('../models/politicians');
var allMongo = require('./all-mongo');

/* GET home page. */
router.get('/', function(req, res, next) {
    'use strict';
    res.render('index', {title: 'CongressServer'});
});

// here
router.get('/bar', function(request, response) {
    response.status(200).send({result: 'bar'});
});

router.get('/bar/:id', function(request, response) {
    'use strict';
    response.status(200).send({param: request.params.id});
});

module.exports = router;

All Mongo

In routes\/all-mongo.js:

/**
 * Created by charlie on 6/5/16.
 */

const connect = require('./connect');
const Politicians = require('../models/politicians');
const fs = require('fs');
let totalPoliticiansSaved = 0;

function allMongo() {
	use strict;
}

allMongo.numberOfPoliticians = 0;

function insertPolitician(politician, response) {
    'use strict';
    if (!connect.connected) {
        connect.doConnection();
    }
    const newPolitician = new Politicians({
        'firstName': politician.firstName,
        'lastName': politician.lastName,
        'city': politician.city,
        'state': politician.state,
        'zip': politician.zip,
        'phone': politician.phone,
        'website': politician.website,
        'email': politician.email,
        'contact': politician.contact
    });

    console.log('inserting', newPolitician.lastName);

    newPolitician.save(function(err) {
        if (err) {
            throw new Error(err);
        }
        totalPoliticiansSaved++;
        console.log('saved: ', newPolitician.lastName, allMongo.numberOfPoliticians, totalPoliticiansSaved);

        if (totalPoliticiansSaved === allMongo.numberOfPoliticians) {
            response.status(200).send({
                result: 'Success Saving Politicians',
                totalSaved: totalPoliticiansSaved
            });
        }
    });
}

allMongo.getAllData = function(response) {
    console.log('About to find politicians.');
    Politicians.find({}, function(err, allData) {
        if (err) {
            throw new Error(err);
        }
        console.log(allData.length);
        console.log(allData[0]);

        allMongo.writeData('politicians.json', allData);

        response.status(200).send({
            result: 'Success',
            allData: allData
        });
    });
};

allMongo.writeData = function(fileName, data) {
    'use strict';
    const dataAsString = JSON.stringify(data, null, 4);
    fs.writeFile(fileName, dataAsString, function(err, result) {
        if (err) {
            throw (err);
        }
        console.log('success writing file');
    });
};

allMongo.readDataAndInsert = function(response) {
    'use strict';
    fs.readFile('public/address-list.json', function(err, politiciansText) {
        if (err) {
            //throw (err);
            response.status(404).send({'result': err});
            return;
        }
        politiciansText = JSON.parse(politiciansText);
        totalPoliticiansSaved = 0;
        allMongo.numberOfPoliticians = politiciansText.length;
        for (let i = 0; i < politiciansText.length; i++) {
            insertPolitician(politiciansText[i], response);
        }
    });
};

allMongo.empty = function(response) {
    Politicians.remove({}, function(err) {
        if (err) {
            response.status(500).send({
                result: 'err',
                err: err
            });
        } else {
            response.status(200).send({
                result: 'collection removed'
            });
        }
    });
};

allMongo.update = function(requestQuery, response) {
    console.log('All Mongo', requestQuery._id);
    Politicians.findOne({
        _id: requestQuery.id
    }, function(err, doc) {
        console.log('findone', err, doc);
        if (err) {
            response.status(404).send({
                result: err
            });
        } else {
            if (doc === null) {
                insertPolitician(requestQuery, response);
            } else {
                doc.firstName = requestQuery.firstName;
                doc.save();
                response.status(200).send({
                    result: 'success',
                    query: requestQuery.body
                });
            }
        }
    });
};

module.exports = allMongo;

Another query

This section is optional. Don’t do it unless you are comfortable with it.

There is a utility called mongo. You can use it to connect to your database, even the database on mlab. At least I think you can.

Install the mongo client only. Then use the string found near the top of mlab database page to connect:

mongo ds049848.mlab.com:49848/elvenlab01 -u <dbuser> -p <dbpassword>

Don’t forget to open a terminal and type mongo to start the mongo shell. Then do something like this:

show dbs
use test
show collections
db.politicians.find()
db.politicians.find({} , {_id: 0, firstName: 1, lastName: 1})

Turn it in

Push you code to your repository, and when you turn it in tell me the tag, branch and folder where it resides. For instance:

  • Folder: XXX
  • Branch: YYY
  • TAG: ZZZ

Please try to keep it simple. I shouldn’t have to wade through several pages of text just to find where you pushed your code.

Additional Notes

Things to remember. Ignore comments about grunt check for now.

Mongoose Basics Connect

After you run grunt check, run your tests and your program again to make sure everything still works!

Mongoose Basics Empty Collection

Notice that emptyCollection has now changed and contains a check to make sure you are connected. The assignment now has the right code.

Match get and post

Here we do a get on the client:

var jqxhr = $.get(insertUrl, function(result) { ... })

Here is the server side, which is also a get:

router.get('/insertValidCollection', function(request, response) { ... })

If you do a get on the client, do a get on the server. Don’t do a get in one place and post in the other. (I had this mixed up in one version of the assignment. You need to get this cleaned up if you followed my example and made a mistake.)

Some More Code

In index.js:

var express = require('express');
var router = express.Router();
var allMongo = require('./all-mongo');
var connect = require('./connect');

/* GET home page. */
router.get('/', function(req, res) {
    'use strict';
    res.render('index', {title: 'CongressServer'});
});

function checkConnection() {
    if (!connect.connected) {
        connect.doConnection('mlab');
    }
}

router.get('/all-data', function(request, response) {
    'use strict';
    console.log('AllData route invoked.');
    checkConnection();
    allMongo.getAllData(response);
});

router.get('/emptyCollection', function(request, response) {
    'use strict';
    checkConnection();
    allMongo.empty(response);
});

router.get('/insertValidCollection', function(request, response) {
    'use strict';
    console.log('Insert Valid Collection Called.');
    response.status(200).send({result: 'Insert valid Collection'});
    //checkConnection();
    //allMongo.readDataAndInsert(response);
});

router.get('/update', function(request, response) {
    'use strict';
    checkConnection();
    console.log('request query', request.query);
    allMongo.update(request.query, response);
});

// Additional Code here.

Query Data

You can also query the data from the mongo app:

db.politicians.find({}, {“_id”: 0, firstName: 1, “lastName”: 1}); { “firstName” : “Rogers”, “lastName” : “Wickers” } { “firstName” : “Timothy”, “lastName” : “Kaine” } { “firstName” : “Angus”, “lastName” : “King” } { “firstName” : “Bob”, “lastName” : “Corker” } { “firstName” : “Amy”, “lastName” : “Klobuchar” } { “firstName” : “Christopher”, “lastName” : “Murphy” } { “firstName” : “Thomas”, “lastName” : “Carper” } { “firstName” : “Benjamin”, “lastName” : “Cardin” }

For more details, see Elvenware on MongoDb.