MongoDB with Mongoose

MongoDB is a popular NoSQL database known for its scalability, flexibility, and ease of use. Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js, providing a straightforward schema-based solution to model application data. This chapter will delve into integrating MongoDB with Mongoose in a Node.js application, covering everything from basic setup to advanced features. By the end of this chapter, you will have a comprehensive understanding of how to use MongoDB with Mongoose effectively.

MongoDB

MongoDB is a document-oriented NoSQL database that stores data in JSON-like documents. It is designed to handle a large amount of data with high performance and scalability. MongoDB is schema-less, allowing flexible data structures and making it suitable for various applications, including real-time analytics, content management systems, and more.

Mongoose

Mongoose is an ODM library that provides a schema-based solution to model application data for MongoDB. It offers powerful features such as schema validation, middleware, and easy-to-use methods for querying and manipulating data. Mongoose helps enforce data consistency and structure, making it easier to work with MongoDB.

Setting Up the Environment

To get started with MongoDB and Mongoose, you need to set up your development environment. Ensure you have Node.js and npm installed, and MongoDB running on your system.

  1. Initialize a Node.js project:

				
					mkdir mongoose-example
cd mongoose-example
npm init -y

				
			

2.Install necessary packages:

				
					npm install express mongoose body-parser

				
			

Connecting to MongoDB with Mongoose

To connect to MongoDB using Mongoose, you need to establish a connection in your Node.js application.

  1. Create a connection file:

				
					// db/connection.js
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/mongoose-example', {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
  console.log('Connected to MongoDB!');
});

module.exports = mongoose;

				
			

2.Use the connection in your application:

				
					// app.js
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('./db/connection');

const app = express();
app.use(bodyParser.json());

const port = 3000;
app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

				
			

Defining Schemas and Models

Schemas define the structure of documents within a collection in MongoDB. Models are constructors compiled from schemas that provide an interface to the database for creating, querying, updating, and deleting documents.

Define a User schema and model

				
					// models/user.js
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true,
    unique: true
  },
  age: {
    type: Number,
    min: 0
  }
});

const User = mongoose.model('User', userSchema);

module.exports = User;

				
			

CRUD Operations

Create a new user:

				
					// app.js (continued)
const User = require('./models/user');

app.post('/users', async (req, res) => {
  try {
    const user = new User(req.body);
    await user.save();
    res.status(201).json(user);
  } catch (err) {
    res.status(400).json({ message: err.message });
  }
});

				
			

Read all users:

				
					// app.js (continued)
app.get('/users', async (req, res) => {
  try {
    const users = await User.find();
    res.status(200).json(users);
  } catch (err) {
    res.status(500).json({ message: err.message });
  }
});

				
			

Update a user:

				
					// app.js (continued)
app.put('/users/:id', async (req, res) => {
  try {
    const user = await User.findByIdAndUpdate(req.params.id, req.body, { new: true });
    if (!user) {
      return res.status(404).json({ message: 'User not found' });
    }
    res.status(200).json(user);
  } catch (err) {
    res.status(400).json({ message: err.message });
  }
});

				
			

Delete a user:

				
					// app.js (continued)
app.delete('/users/:id', async (req, res) => {
  try {
    const user = await User.findByIdAndDelete(req.params.id);
    if (!user) {
      return res.status(404).json({ message: 'User not found' });
    }
    res.status(200).json({ message: 'User deleted successfully' });
  } catch (err) {
    res.status(500).json({ message: err.message });
  }
});

				
			

Querying the Database

Mongoose provides various methods for querying the database.

  1. Find by specific criteria:

				
					// Find users by age
app.get('/users/age/:age', async (req, res) => {
  try {
    const users = await User.find({ age: req.params.age });
    res.status(200).json(users);
  } catch (err) {
    res.status(500).json({ message: err.message });
  }
});

				
			

2.Pagination and sorting:

				
					// Paginate and sort users
app.get('/users/page/:page', async (req, res) => {
  const page = parseInt(req.params.page, 10) || 1;
  const limit = 10;
  const skip = (page - 1) * limit;

  try {
    const users = await User.find().skip(skip).limit(limit).sort({ name: 1 });
    res.status(200).json(users);
  } catch (err) {
    res.status(500).json({ message: err.message });
  }
});

				
			

Validations and Middleware

Validations

Mongoose provides built-in validators and custom validation functions.

  1. Built-in validations:

				
					// models/user.js (continued)
const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true,
    unique: true,
    match: /.+\@.+\..+/
  },
  age: {
    type: Number,
    min: 0,
    max: 120
  }
});

				
			

2.Custom validations:

				
					// models/user.js (continued)
userSchema.path('email').validate(async (email) => {
  const emailCount = await mongoose.models.User.countDocuments({ email });
  return !emailCount;
}, 'Email already exists');

				
			

Middleware

Middleware functions are executed during the lifecycle of a document. They can be used for tasks such as validation, logging, and modifying documents.

  1. Pre-save middleware:

				
					// models/user.js (continued)
userSchema.pre('save', function (next) {
  console.log(`User ${this.name} is being saved`);
  next();
});

				
			

2.Post-save middleware:

				
					// models/user.js (continued)
userSchema.post('save', function (doc) {
  console.log(`User ${doc.name} has been saved`);
});

				
			

Advanced Features

Virtuals

Virtuals are document properties that do not persist to the database. They can be used for computed properties.

  1. Define a virtual property:

				
					// models/user.js (continued)
userSchema.virtual('fullName').get(function () {
  return `${this.firstName} ${this.lastName}`;
});

				
			

Population

Population is a process of automatically replacing specified paths in the document with documents from other collections.

  1. Define reference in schema:

				
					// models/user.js (continued)
const userSchema = new mongoose.Schema({
  name: String,
  email: String,
  posts: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Post' }]
});

				
			

2.Populate reference fields:

				
					// app.js (continued)
app.get('/users/:id', async (req, res) => {
  try {
    const user = await User.findById(req.params.id).populate('posts');
    res.status(200).json(user);
  } catch (err) {
    res.status(500).json({ message: err.message });
  }
});

				
			

In this chapter, we covered integrating MongoDB with Mongoose in a Node.js application. We explored basic setup, schema and model definition, CRUD operations, querying, validations, middleware, and advanced features like virtuals and population. With the comprehensive information and practical examples provided, you should have a solid understanding of using MongoDB with Mongoose in your Node.js projects.Happy coding !❤️

Table of Contents

Contact here

Copyright © 2025 Diginode

Made with ❤️ in India