Optimizing Node Application with MongoDB
In this tutorial, discover how to seamlessly integrate MongoDB with your Node.js application. From creating an administrative user to implementing Mongoose schemas and controllers – learn how to efficiently manage your data and optimize your application.
When working with Node.js, you may need to develop a project that stores and queries data. In this case, you need to select a database solution that makes sense for your application’s data and query types.
In this tutorial, you will integrate a MongoDB database into an existing Node application. NoSQL databases like MongoDB can be useful when your data requirements include scalability and flexibility. MongoDB also integrates well with Node as it’s designed to work asynchronously with JSON objects.
To integrate MongoDB into your project, you’ll use the Object Document Mapper (ODM) Mongoose to create schemas and models for your application data. This allows you to organize your application code following the Model-View-Controller (MVC) architecture pattern, which separates the logic of how your application handles user input from the structure of your data and how it is presented to the user. Using this pattern can make future testing and development easier by introducing a separation of concerns in your code.
At the end of the tutorial, you will have a working shark information application that takes user input about their favorite sharks and displays the results in the browser.
Prerequisites
- A local development machine or server running Ubuntu 18.04, along with a non-root user with sudo privileges and an active firewall.
- Node.js and npm installed on your machine or server, following the instructions for installation with NodeSource’s PPA.
- MongoDB installed on your machine or server, following Step 1 of How to Install MongoDB on Ubuntu 18.04.
Step 1: Creating a Mongo User
Before working on the application code, we’ll create an administrative user with access to our application’s database.
First, check if MongoDB is running on your server:
sudo systemctl status mongodb
Then open the Mongo shell to create your user:
mongo
In the shell, use the `use admin` command to use the admin database to create your user. Replace `sammy` and `your_password` with your own username and password.
use admin
db.createUser(
{
user: “sammy”,
pwd: “your_password”,
roles: [ { role: “userAdminAnyDatabase”, db: “admin” } ]
}
)
With the user created, you can now exit the Mongo shell:
exit
Step 2: Adding Mongoose and Database Information to the Project
First, clone the project’s initial code and add Mongoose and your MongoDB database information.
Clone the repository into a directory named `node_project`:
git clone https://github.com/do-community/nodejs-image-demo.git node_project
Then add the Mongoose npm package to the project:
npm install mongoose
Create a file for your database connection information named `db.js`.
Add the following content to the `db.js` file:
const mongoose = require(‘mongoose’);
const MONGO_USERNAME = ‘sammy’;
const MONGO_PASSWORD = ‘your_password’;
const MONGO_HOSTNAME = ‘127.0.0.1’;
const MONGO_PORT = ‘27017’;
const MONGO_DB = ‘sharkinfo’;
const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;
mongoose.connect(url, {useNewUrlParser: true});
Finally, add the database connection information to the `app.js` file so the application can access it.
Step 3: Creating Mongoose Schemas and Models
Next, think about the structure of the shark collection that users will create with their entries on the application’s shark information page.
Create a schema and model for sharks in a file named `sharks.js`.
Add the following content to the `sharks.js` file:
const mongoose = require(‘mongoose’);
const Schema = mongoose.Schema;
const Shark = new Schema ({
name: { type: String, required: true },
character: { type: String, required: true },
});
module.exports = mongoose.model(‘Shark’, Shark)
Step 4: Creating Controllers
Create a controller to define how user inputs are stored and returned to the user.
Create a controller in a file named `sharks.js` in the `controllers` directory.
Add the following content to the `sharks.js` file:
const path = require(‘path’);
const Shark = require(‘../models/sharks’);
exports.index = function (req, res) {
res.sendFile(path.resolve(‘views/sharks.html’));
};
exports.create = function (req, res) {
var newShark = new Shark(req.body);
newShark.save(function (err) {
if(err) {
res.status(400).send(‘Unable to save shark to database’);
} else {
res.redirect(‘/sharks/getshark’);
}
});
};
exports.list = function (req, res) {
Shark.find({}).exec(function (err, sharks) {
if (err) {
return res.send(500, err);
}
res.render(‘getshark’, {
sharks: sharks
});
});
};
Step 5: Setting Up Express Middleware
To enable our application to work with user data, we need to do two things: First, we’ll include a built-in Express middleware function called `urlencoded()` that allows our application to parse user-entered data. Second, we’ll add template tags to our views to enable dynamic interaction with user data in our code.
To do this, first open your `app.js` file and add the following line above the `express.static()` function:
app.use(express.urlencoded({ extended: true }));
This function enables access to the parsed POST data of our shark information system. The `extended: true` option allows greater flexibility when parsing different types of data.
Step 6: Adding EJS Tags for Dynamic Interaction
To render dynamic content based on user data in our views, we add template tags. First, install the EJS package with npm:
npm install ejs
Then open your view file `sharks.html` and add a form where users can enter information about sharks. Also, add template tags to dynamically render this data.
By using template tags and JavaScript syntax, we can map user inputs to the respective fields in our data model.
Step 7: Setting Up Routing and Controller Logic
To make the application dynamic and handle user data, we need to set up routes and controller logic. This involves creating routes to display shark information and add new sharks.
router.get(‘/’, function(req, res){
shark.index(req,res);
});
router.post(‘/addshark’, function(req, res) {
shark.create(req,res);
});
These routes use the respective functions in our Shark controller to perform the requested actions.
Conclusion
Using EJS and Express middleware, we can collect and dynamically render user data on our website. This allows for user-friendly interaction and opens up numerous possibilities for building dynamic web applications.