Skip to content
FullStackDost Logo
  • All Courses
  • Blogs
  • Login
  • Register
  • All Courses
  • Blogs
  • Login
  • Register
  • Home
  • All Courses
  • Web development
  • MongoDB – (No-SQL)

MongoDB – (No-SQL)

Curriculum

  • 10 Sections
  • 31 Lessons
  • 10 Weeks
Expand all sectionsCollapse all sections
  • Introduction to MongoDB
    MongoDB is a NoSQL database that is designed for handling large volumes of unstructured or semi-structured data. Unlike traditional relational databases (RDBMS) that use tables and rows to organize data, MongoDB stores data in a flexible document-oriented format using JSON-like documents (BSON - Binary JSON). This makes it highly scalable, flexible, and performant for applications that need to handle varying types of data with complex structures.
    5
    • 1.1
      What is MongoDB?
    • 1.2
      Why MongoDB?
    • 1.3
      When to use MongoDB?
    • 1.4
      Key Features of MongoDB
    • 1.5
      Installing MongoDB
  • MongoDB Basic Operations
    MongoDB provides a rich set of basic operations for interacting with the database, including creating, reading, updating, and deleting data (often abbreviated as CRUD operations). Below are the basic operations that you can perform with MongoDB.
    2
    • 2.0
      Database and Collection Basics
    • 2.1
      CRUD Operations
  • Advanced Querying Techniques
    MongoDB offers a rich set of querying capabilities, and as you work with larger datasets and more complex application requirements, you’ll often need to use advanced querying techniques. These techniques help you optimize performance, execute sophisticated queries, and leverage MongoDB’s powerful indexing and aggregation features.
    4
    • 3.1
      Query Filters and Operators
    • 3.2
      Advanced Querying
    • 3.3
      Sorting and Limiting Results
    • 3.4
      Aggregation Framework
  • Data Modeling and Schema Design
    Data modeling and schema design are critical when using MongoDB (or any NoSQL database) to ensure efficient data storage, fast queries, and scalability. Unlike relational databases, MongoDB is schema-less, which means you are not required to define a fixed schema upfront. However, making the right design decisions from the beginning is essential for maintaining performance and avoid complications as your data grows.
    4
    • 4.1
      Data Modeling
    • 4.2
      Document Structure
    • 4.3
      Schema Design Patterns
    • 4.4
      MongoDB and Relationships
  • Indexing and Performance Optimization
    In MongoDB, indexing is a critical part of performance optimization. Without proper indexes, MongoDB has to scan every document in a collection to satisfy queries, which can be very inefficient for large datasets. Indexes are used to quickly locate data without scanning every document, making reads faster and more efficient.
    3
    • 5.0
      Creating Indexes
    • 5.1
      Using Text Search
    • 5.2
      Performance Optimization
  • Integrating MongoDB with a Web Application (Node.js)
    Integrating MongoDB with a web application built using Node.js is a common and powerful combination for building scalable and efficient web apps. MongoDB’s flexibility with JSON-like data and Node.js's asynchronous event-driven architecture work well together. In this guide, I'll walk you through the steps for integrating MongoDB with a Node.js web application, covering the essentials of setting up the connection, performing CRUD operations, and using popular libraries.
    3
    • 6.0
      Setting Up MongoDB with Node.js
    • 6.1
      CRUD Operations with Mongoose
    • 6.2
      Error Handling and Validation
  • Security in MongoDB
    Security is an essential aspect when working with MongoDB, especially when handling sensitive data in production environments. MongoDB provides a variety of security features to help protect your data against unauthorized access, injection attacks, and other vulnerabilities. Here’s a guide on securing MongoDB and your Node.js application when interacting with MongoDB.
    2
    • 7.0
      Authentication and Authorization
    • 7.1
      Data Encryption
  • Working with MongoDB in Production
    3
    • 8.0
      MongoDB Backup and Restore
    • 8.1
      MongoDB Scaling and Sharding
    • 8.2
      MongoDB Replication
  • Deploying and Monitoring MongoDB
    Working with MongoDB in a production environment requires careful planning, attention to detail, and best practices to ensure optimal performance, security, reliability, and scalability.
    3
    • 9.0
      Deploying MongoDB to Production
    • 9.1
      Monitoring and Management
    • 9.2
      Summary for MongoDB deployment on Production
  • Building a Web App with MongoDB (Final Project)
    Demo Project (OneStopShop)
    2
    • 10.0
      Building the Application
    • 10.1
      Final Project Features

Error Handling and Validation

Error handling and validation are critical aspects of building robust MongoDB applications with Node.js. With Mongoose, you can implement both server-side validation and proper error handling to ensure data integrity, handle errors gracefully, and provide meaningful feedback to the client.

1. Validation in Mongoose

Mongoose provides built-in validation for data integrity, such as type checking, required fields, uniqueness, and custom validation logic.

Built-in Validation Types

Mongoose allows you to define validation rules at the schema level. Here are some common validation rules:

  • Required: Ensures a field is not empty.
  • Min/Max: Ensures a value is within a given range.
  • Match: Validates a value against a regular expression.
  • Enum: Ensures a value is one of a predefined set of values.
  • Unique: Ensures no two documents have the same value for a field (this validation is handled at the database level and requires unique: true).

Example Schema with Validation

Let’s update the User model with validation rules.

javascript

Copy code

// userModel.js const mongoose = require('mongoose'); // Define the schema with validation rules const userSchema = new mongoose.Schema({ name: { type: String, required: [true, 'Name is required'], // Custom error message for required field minlength: [3, 'Name must be at least 3 characters long'], // Min length validation }, email: { type: String, required: [true, 'Email is required'], unique: true, // Ensure email is unique across users match: [/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/, 'Please enter a valid email address'] // Regex for email format }, age: { type: Number, required: [true, 'Age is required'], min: [18, 'Age must be at least 18'], // Age validation max: [120, 'Age must be below 120'] // Max age validation } }); // Create the model const User = mongoose.model('User', userSchema); module.exports = User;

In this schema, we:

  • Set name, email, and age to be required.
  • Added minimum length for the name field.
  • Added a regex for the email format.
  • Enforced a minimum age of 18 and maximum age of 120.

Custom Validation

Mongoose also allows you to define custom validation logic using the validate keyword.

For example, if we want to ensure that the email field is not the same as a hardcoded list of “blacklisted” emails:

javascript

Copy code

const blacklistedEmails = ['blacklisted@example.com', 'spam@example.com']; const userSchema = new mongoose.Schema({ email: { type: String, required: [true, 'Email is required'], validate: { validator: (email) => !blacklistedEmails.includes(email), message: 'This email is blacklisted.' } } });

2. Error Handling in Mongoose

Handling errors properly is essential for providing feedback and ensuring that the application behaves correctly in case of invalid input, database issues, or other failures.

Handling Validation Errors

When you try to save a document in Mongoose and validation fails, Mongoose throws a ValidationError. To handle this error, you can use a try/catch block or handle it asynchronously.

Here’s an example of handling validation errors during the creation of a user:

javascript

Copy code

// server.js app.post('/users', async (req, res) => { const { name, email, age } = req.body; try { const newUser = new User({ name, email, age }); await newUser.save(); // This will throw validation errors if validation fails res.status(201).json(newUser); } catch (err) { if (err.name === 'ValidationError') { // Handle Mongoose validation errors const errorMessages = Object.values(err.errors).map(e => e.message); return res.status(400).json({ errors: errorMessages }); } res.status(500).json({ error: 'An unexpected error occurred.' }); } });

Error Handling Strategy:

  1. Validation Errors: If the error is a ValidationError, we extract and return the error messages.
  2. Database Errors: If a MongoDB error occurs (e.g., when trying to insert a duplicate entry), we handle it appropriately.
  3. Unknown Errors: For any other errors, we return a generic error message.

3. Handling MongoDB Errors (e.g., Unique Constraint Violations)

Mongoose can throw different kinds of errors. One common issue is duplicate key errors (for example, when trying to insert a document with a duplicate email field when the email field is set to unique: true).

Here’s how you can handle duplicate key errors (such as for the email field):

javascript

Copy code

app.post('/users', async (req, res) => { const { name, email, age } = req.body; try { const newUser = new User({ name, email, age }); await newUser.save(); res.status(201).json(newUser); } catch (err) { if (err.name === 'ValidationError') { // Handle Mongoose validation errors const errorMessages = Object.values(err.errors).map(e => e.message); return res.status(400).json({ errors: errorMessages }); } if (err.code === 11000) { // Handle duplicate key error (MongoDB unique constraint violation) return res.status(400).json({ error: 'Email already exists.' }); } res.status(500).json({ error: 'An unexpected error occurred.' }); } });

  • The err.code === 11000 is a specific MongoDB error code for a duplicate key violation.
  • In this case, we specifically catch the error and send a response that the email is already taken.

4. Async/Await Error Handling

Mongoose uses promises for database operations, so you can take advantage of async/await for clean error handling.

Here’s how you can handle errors with async/await for all CRUD operations:

Example with Create Operation:

javascript

Copy code

app.post('/users', async (req, res) => { const { name, email, age } = req.body; try { const newUser = new User({ name, email, age }); await newUser.save(); // Await for the save operation res.status(201).json(newUser); // Send success response } catch (err) { if (err.name === 'ValidationError') { const errorMessages = Object.values(err.errors).map(e => e.message); return res.status(400).json({ errors: errorMessages }); // Send validation errors } else if (err.code === 11000) { return res.status(400).json({ error: 'Email already exists.' }); // Handle duplicate email error } else { console.error(err); // Log other unexpected errors res.status(500).json({ error: 'An unexpected error occurred.' }); // Send generic error } } });

5. General Error Handling Middleware

You can also create a generic error handler in your Express app to catch unhandled errors:

javascript

Copy code

// Generic error handler app.use((err, req, res, next) => { console.error(err); // Log the error (could be enhanced with logging libraries) if (err instanceof mongoose.Error) { return res.status(500).json({ error: 'Database error occurred.' }); } res.status(500).json({ error: 'An unexpected error occurred.' }); });

This middleware will catch any errors thrown by routes or asynchronous code and ensure that an appropriate error message is sent to the client.

Conclusion

  1. Validation: You can enforce field validation rules directly in your Mongoose schema (required fields, min/max values, regex matching, custom validation, etc.).
  2. Error Handling: Mongoose throws different kinds of errors, such as validation errors, duplicate key errors, and general database errors. You can handle these with try/catch blocks and check for specific error types (like ValidationError and 11000 for duplicate keys).
  3. Centralized Error Handling: Consider implementing a global error handler in your Express app to catch unhandled errors and respond with appropriate error messages.
  4. Custom Error Messages: Make sure to provide meaningful and user-friendly error messages when validation fails or database errors occur.

By handling validation and errors effectively, you ensure that your Node.js application is robust, secure, and user-friendly.

CRUD Operations with Mongoose
Prev
Authentication and Authorization
Next

Copyright © 2025 FullStackDost. All Rights Reserved.

Theme by ILOVEWP