in

Introduction to MongooseJS

Mongoose JS is essentially a framework or schema that makes it easy to pass data between a Node.js application and a MongoDB Database. It’s definitely not necessary to accomplish this task, but makes life much easier by scaffolding a lot of the boilerplate for you, such as validation.

Technically it is an Object Data Mapper (ODM), it is a Javascript layer on top of MongoDB that allows us to interact with our database.

Setting up Mongoose

Let’s start by making a demo application on a Node.js server (no Express or EJS yet, just Node). First make sure that you have installed a MongoDB server and it is running. This process was covered here: Introduction to Mongo DB

Next we setup our application file mongoose.js according to the official Mongoose docs: Mongoose Docs

/*------------------------------------------
SETUP
------------------------------------------*/

// requiring mongoose in app
var mongoose = require("mongoose");

// connecting Mongo database
mongoose.connect('mongodb://localhost/icecream', {useNewUrlParser: true, useUnifiedTopology: true});

var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
  console.log("MongoDB Connected");
});

Now we have connected to a MongoDB titled icecream. Before we can add our different ice cream flavors to the database, we need to define a schema.

Schema

What is the point of using a schema if we are creating a non-relational database? This is not a locked in format like it would be in a relational database, however we do need to have a certain amount of predictability for our code to be able to handle our data properly. We can always change this later.

Here is a sample schema from the Mongoose Docs:

 var mongoose = require('mongoose');
  var Schema = mongoose.Schema;

  var blogSchema = new Schema({
    title:  String,
    author: String,
    body:   String,
    comments: [{ body: String, date: Date }],
    date: { type: Date, default: Date.now },
    hidden: Boolean,
    meta: {
      votes: Number,
      favs:  Number
    }
  });

Here is the schema that we will use for our sample Ice Cream database:

/*------------------------------------------
SCHEMA
------------------------------------------*/
var iceCreamSchema = new mongoose.Schema({
    flavor:  String,
    delicious: Boolean,
    calories: Number,
    description: String
  });

For each item in the object we define the expected data type. Schemas like this are what allows Mongoose to perform it’s functionality, such as validation.

Model

After we have defined a schema we have to compile our schema into a model. A model is a class with which we construct documents. In this case, each document will be an ice cream with properties and behaviors as declared in our schema.

The model is what allows us to run methods on our objects.

// compile to Model
var IceCream = mongoose.model('IceCream', iceCreamSchema);

In short, the variable IceCream is a Mongoose model, named IceCream which follows the schema named iceCreamSchema. Up to this point this is essentially all just setup. Now we can start defining our different ice cream flavors.

Custom Methods

We will learn about the built in methods such as .save in just a minute, but this is the time to note that we can create custom methods on our schema. Custom methods must be place before model compilation.

Here we create a custom method .display which logs a different message depending on whether the flavor of the selected ice cream has been defined.

/*------------------------------------------
CUSTOM METHODS - Must Go Before COMPILE
------------------------------------------*/

iceCreamSchema.methods.display = function () {
  var consoleFlavor = this.flavor
    ? "Flavor is: " + this.flavor
    : "Flavor unknown";
  console.log(consoleFlavor);
}

/*------------------------------------------
COMPILE TO MODEL - METHODS Must Go Before
------------------------------------------*/
var IceCream = mongoose.model('IceCream', iceCreamSchema);

Sample Data

Now let us create some sample data, to model what we would be receiving from HTTP POST requests.

/*------------------------------------------
SAMPLE DATA
------------------------------------------*/

var rockyRoad = new IceCream({
    flavor:  "Rocky Road",
    delicious: false,
    calories: 500,
    description: "Rocky road ice cream is a chocolate flavored ice cream. Though there are variations from the original flavor, it is traditionally composed of chocolate ice cream, nuts, and whole or diced marshmallows."
});

var cookieDough = new IceCream({
    flavor:  "Cookie Dough",
    delicious: true,
    calories: 750,
    description: "Chocolate chip cookie dough ice cream is a popular ice cream flavor in which unbaked chunks of chocolate chip cookie dough are embedded in vanilla flavored ice cream."
});

// our custom method as defined above
rockyRoad.display()
cookieDough.display()

Saving Data to MongoDB Database

All of the data above is just living in our JS file. Nothing has actually been saved to the Mongo database yet. To do that we use .save.

.save

Select the data by selecting its variable and then apply the .save method. This method has an optional callback function that gives the error and data. In this sample if there is no error the data is console.log’d using the custom method “display” that we defined above.

/*------------------------------------------
SAVE DATA TO MONGODB - .save Method
------------------------------------------*/

rockyRoad.save(function (err, rockyRoad){
  if (err) return console.error(err);
  rockyRoad.display();
});

cookieDough.save(function (err, rockyRoad){
  if (err) return console.error(err);
  cookieDough.display();
});

Display Data

.find

To display all of the data in the database so far, we have the .find method. It also has a built in callback function that gives you the option to show any errors and the data that you have requested.

/*------------------------------------------
DISPLAY DATA - .find Method
------------------------------------------*/

IceCream.find(function (err, iceCreams){
  if (err) return console.error(err);
  console.log(iceCreams);
});

and we can see that we have retrieved the data from the MongoDB because of the unique ID that has been assigned.

GitHub Repo

Introduction to MongoDB

Frosty CMS: Creating a Blog CMS from Scratch (Features and Wireframe)