Mongoose ORM basic usage

Mongoose is an ODM ( Object Document mapper ) for node js & mongo db. It map mongo collections to node js models to provide object oriented way of db operations. It can be installed by using npm in current project directory.

$ npm install mongoose --save

Connection can be made in out app/controller files by

var mongoose = require('mongoose');
 mongoose.connect('mongodb://HOSTNAME/DBNAME');

Now we need to add model file for our collections.

We will create following models ->

models/test.js

Let see test model code

const mongoose = require('mongoose')
let Schema = mongoose.Schema;

const TestSchema = new Schema(
{
 string_col: {type: String, default: ''},
 number_col: {type: Number, default: 0},
 bool_col: {type: Boolean, default: null},
 mixed_col: {type: Schema.Types.Mixed, default: ''},
 oid_col: {type: Schema.Types.ObjectId, default: null},
 array_col: [{type: String, default: ''}],
 date_col: { type: Date, default: Date.now() }
})

const testModel = mongoose.model('test', TestSchema);
module.exports = testModel;

Here we describe a schema for mongo collection. Key column _id is automatically added and need not to be described. Fields are described by their types. Following types are supported.

a) String
String type defined for string type fields.

b) Number
Number type defined for number (both) type fields.

c) Bool
Bool type can have boolean values true & false.

d) mixed
Mixed type can have any type. It is mainly used when data is uncertain.

e) ObjectId
Mongo key object id field. Mainly used for foreign key implementation from same / other collection key.

f) Date
Date type handle ISO Date formatted data like ISODate(“2018-03-19T12:51:01.585Z”)

g) Array
This type used to insert array type of data. We can define other type as valid values in array like
[{type: String}]
[{type: Number}]
[{type: Mixed}]
[{type: Date}]

We can create multi level array by using following syntax

[[{type: String}]]

If we do not define type and used syntax like [] or [[]]. Field can have any type of data as values of array.

We can used mongoose save API call to save data into collection.

var testModel = require('./models/test');
var testObj = new testModel();
testObj.string_col = 'Kuldeep';
testObj.number_col = 1234;
testObj.mixed_col = {'age': 45};
testObj.array_col = ['John', 'Doe'];
testObj.bool_col = true;
testObj.oid_col = mongoose.Types.ObjectId("5906d4017362098740b23eeb");
testObj.date_col = new Date();
testObj.save((err, res) => {
if (err) return console.error(err);
   console.log('SAVED;')
   mongoose.disconnect(); 
});

This call create new Object for test model with required properties and save call insert data to collection.

If we need to update data we can use either findOneAndUpdate or Save call

USING findOneAndUpdate

testModel.findOneAndUpdate(
  {_id: mongoose.Types.ObjectId("5aafb50bd1443f49a873784c")}, {
  { $set: {
    string_col: "New Str"
  }
 }, {
   upsert: false
 }, (err, res) => {
    if (err) return console.error(err);
    console.log('SAVED;')
    mongoose.disconnect();
}
);

First argument is condition on which single record is chosen to save.
Second argument have fields to update.
Third argument is optional. If set upsert true, It insert the data as new record if no matching record with condition was found.

findOne + Save Method

testModel.findOne({_id: mongoose.Types.ObjectId("5aafb50bd1443f49a873784c")}, (err, testObj) => {
  if (err) return console.error(err);
  testObj.string_col = 'NEW DATA';
  testObj.save((err, res) => {
  if (err) return console.error(err);
     console.log('SAVED;')
     mongoose.disconnect();
  });
});

This method is similar to insert method as we used same save call to update data, Except we do not used new Model, but get object from DB by using findOne call.

REST using Node/Express & Mongoose

NodeJS is fast growing language in today environment. For web their are several frameworks but Express web framework  is most used framework for web development in node js.

So how to make a sample Rest API in express / Node JS ?

First setup express using npm. So we use following commands to get npm init & require packages install.

# add package json
$ npm init

$ npm install --save express
$ npm install --save mongoose body-parser

Above commands install express framework in node modules. Then it install http request parser package plus ODM package for mongo db called mongoose. Now it is time to do some coding. First create main application file app.js & put following code.

var express = require('express');
var app = express();
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');


// var UserController = require('./controllers/UserController');
// app.use('/users', UserController);

var port = process.env.PORT || 3000;
var server = app.listen(port, function() {
      console.log('Express server listening on port ' + port);
});

module.exports = app;

Update package.json to set tell about main script

"scripts": {
       "start": "node app.js"
 }

You can run this code by

$ npm start

Which start the server at 3000 port. You can check http://localhost:3000 which show “Cannot GET /” because we did not setup router. So we add a User Module. for this we need to add controller & model. So create two directories controllers & models for better code maintaining.  Add Following mongoose based code in models/User.js file.

var mongoose = require('mongoose');
var UserSchema = new mongoose.Schema({
    name: String,
    email: String,
    password: String
});
mongoose.model('User', UserSchema);
module.exports = mongoose.model('User');

Now Setup controller file controllers/UserController.js which also work as router for User APIs.

var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
router.use(bodyParser.urlencoded({ extended: true }));

var User = require('../models/User');

router.post('/', function (req, res) {

    User.create({
        name : req.body.name,
        email : req.body.email,
        password : req.body.password
    },
    function (err, user) {
        if (err) return res.status(500).send("There was a problem adding the information to the database.");
        res.status(200).send(user);
    });

});

// RETURNS ALL THE USERS IN THE DATABASE
router.get('/', function (req, res) {

    User.find({}, function (err, users) {
        if (err) return res.status(500).send("There was a problem finding the users.");
        res.status(200).send(users);
     });

});

// RETURNS USER DETAILS IN THE DATABASE
router.get('/:id', function (req, res) {

    User.findOne({"_id":req.params.id}, function (err, users) {
        if (err) return res.status(500).send("There was a problem finding the users.");
        res.status(200).send(users);
    });

});

// UPDATE USER DETAILS IN THE DATABASE
router.put('/:id', function (req, res) {

    User.update({"_id":req.params.id}, {
        name : req.body.name,
        email : req.body.email,
        password : req.body.password
    }, function (err, users) {
        if (err) return res.status(500).send("There was a problem finding the users.");
        res.status(200).send(users);
    });

});

// DELETE USER FROM THE DATABASE
router.delete('/:id', function (req, res) {
    User.remove({"_id":req.params.id}, function (err, users) {
        if (err) return res.status(500).send("There was a problem finding the users.");
        res.status(200).send(users);
     });

});

module.exports = router;

Now we have out two user APIs ready for insert a single record ( POST ) & get all records ( GET ). But still we need to register router with app, So uncomment lines in app.js

var UserController = require('./controllers/UserController');
app.use('/users', UserController);

Now we have http://localhost:3000/users working as POST & GET method for our APIs. We can test it by invoking respective methods via CURL CLI.

$ curl http://localhost:3000/users
$ curl -X POST -d 'email=kuldeep@gmail.com&name=Kuldeep&password=kamboj' http://localhost:3000/users

$ curl http://localhost:3000/users/5a47d942cb4f00c95de8f511

$ curl -X PUT -d 'email=kuldeepk@gmail.com&name=KuldeepK&password=kamboj' http://localhost:3000/users/5a47d942cb4f00c95de8f511

$ curl -X DELETE  http://localhost:3000/users/5a47d942cb4f00c95de8f511