Getting Started With Express Part 3

With an Expressjs application, you can make use of all popular databases available to perform several operations such as Create, Read, Update and Delete (CRUD operations). This tutorial will provide you an overview of a database, we are going to use with our Expressjs application, called MongoDB. Further, we will be looking into pragmatic concepts like what is an ODM/ORM, Schemas, Models and connecting the MongoDB database with our Express application.

Other popular options that we could use with Expressjs are PostgreSQL, MySQL, SQLite, Redis, etc.

How to interact with a Database using Server side framework like Expressjs

Since there are many options with Express to use a database, choosing the right database in the tech stack is important. But more important is to learn how to approach to interact with a database. There are two ways to do that. First, for a database like SQL you can use native query language. Secondly, you can use an ORM or ODM in case of MongoDB.

An ORM (Object Relational Mapper) or an ODM (Object Data Model) is helpful with connecting a database using JavaScript from inside the Express application. You can define a minimal configuration setting to set it up. Next, the bigger advantage of an ODM is that they also help you to query Database from controllers in an Express application using a similar syntax to JavaScript. There is no need to learn much about native query language. ORM such as Sequelize can interact with the different form of SQL databases.

The benefit of using an ODM/ORM is that we developers can continue to think regarding JavaScript objects rather than database native query language. It will be helpful if you need to work with different databases and in the real world, you will. Some examples of ORM/ODM are:

  • Mongoose for MongoDB
  • Sequelize for PostgreSQL, MySQL, MariaDB, SQLite and MSSQL
  • WaterLine for Redis, mySQL, LDAP, MongoDB, and Postgres
  • Bookshelf for PostgreSQL, MySQL, and SQLite3.

For our example, we will be using Mongoose an ODM from the above list. It is an open source and free to use and favorite in Node.js community.

MongoDB and Mongoose

To use MongoDB, make sure you have installed it in your local machine. You can refer the official documentation for that or if on OS X. You can use a tool like Homebrew. MongoDB is a NoSQL database that stores information in the form of documents. Each document can contain various fields and nested fields to represent the stored data. There can be different documents stored in a collection. A MongoDB database can include multiple collections. These collections of documents are similar to a table of rows if you are familiar with SQL database.

Connecting the Database

To start using mongoose, we will begin by installing it in our project.

npm install -S mongoose

We will now make a database connection. Create a file called dbconfig.js inside config/ directory.

const mongoose = require('mongoose');

// define connection URI string
const DBURI = 'mongodb://localhost/nodejsexample';

// open mongoose connection
mongoose.connect(DBURI);

// Listen to CONNECTION EVENTS
// When successfully connected
mongoose.connection.on('connected', () => {
    console.log('Mongoose Default Connection with : ' + DBURI);
});

// When connection throws an error
mongoose.connection.on('error', err => {
    console.log('Mongoose Default Connection Error : ' + err);
});

// When connection is disconnected
mongoose.connection.on('disconnected', () => {
    console.log('Mongoose Default Disconnected');
});

Then we require this file in our app.js such that when the server runs, the database connection is made. Mongoose emits events for each common scenarios, such as connected when the database is connected. Error when there is an error connecting to a database (currently, we are using a local database instance, but in production env, your data will be stored in cloud service such as mlab, etc.) and can be disconnected when an interruption occurs while the server is running.

// require it after you require other dependencies but before other configuration

require('./config/db.config.js');

var app = express();

Now, if you run the dev server from the terminal:

npm run devstart

You will notice a new message prompt that says Mongoose Default Connection with : mongodb://localhost/nodejsexample.

Defining a Local Schema

We will now describe a schema inside a directory called models, naming it book.model.js. You can use any name. It is just a convention we are using in this example to name our file.

var mongoose = require('mongoose');

var Schema = mongoose.Schema;

var BookSchema = new Schema({
    title: { type: String, required: true },
    author: { type: String, required: true },
    summary: { type: String, required: true },
    isbn: { type: String, required: true },
    genre: [{ type: String }]
});

//Export model
module.exports = mongoose.model('Book', BookSchema);

To define a schema, every time, we need to require Mongoose in each of the schema files like we are doing above. Mongoose provides a constructor method for defining the Schema, like above in our example, BookSchema is an instance of the constructor method mongoose. SchemaIt also offers a way to declare data types while declaring a field, such as title, to identify what kind of value it can store in the database.  So these necessities are needed to be defined with our Server application. Note the data type we are using is String type.

We can also provide attributes required: true, that enforces the database to accept data, only if the field is provided through our API. For example, consider a form when adding a book’s details and we forget to provide the author of the book. On our frontend, we have to make a custom error fields to display the message to the user, but in our backend, the database will not store the data. It will throw an error here. Another commonly used attribute you can use is called unique which helps to make data fields of model distinctive for each document in a collection. For example, the _id of the document. 

Each document in our database will have a unique id that is going to be auto-generated by MongoDB. But in other scenarios, you want to generate an id from the server side using a different convention you do like this:

_id: mongoose.Schema.Types.ObjectId,
    name: {
            firstName: String,
        lastName: String
    }

Notice _id field name. MongoDB stores the unique identifier as _id which has a datatype of ObjectId. By default, this data type is a 12-byte Binary BSON type and is used as a primary key. In your database, you might find it as a string like this:

"_id": ObjectId("54759eb3c090d83494e2d804")

Mongoose also allows flexibility to create schemas with arrays. In our genre field, we can have different String names such as Fiction along with sub-genres such as Mystery which relates to the overall schema.

module.exports = mongoose.model('Book', BookSchema);

Lastly, we export our schema by defining a model. The first argument is the singular name of the schema. This schema name will also be the collection name. We are going to use it in our API to query the database. Mongoose searches for the plural version of the model name automatically. Thus, for example, above, the model Book is for the books collection in the database. The .model() method makes a copy of the schema. We have to make sure that every field is added to the schema before calling mongoose.model() method.

This completes our Book Model. In the next tutorial, we will be using this schema to perform CRUD operations with our database.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.