Days 32-33: Introduction to Mongoose – Models, Schemas, and Data Validation
Mongoose is an Object Data Modeling (ODM) library for MongoDB that simplifies interactions with the database in Node.js applications. It provides a structured way to define database schemas, create models, and enforce data validation.
MongoDB is a schema-less NoSQL database, meaning it doesn’t enforce any predefined structure on documents. However, in large-scale applications, maintaining data consistency is crucial. This is where Mongoose schemas and validation help by ensuring that data follows a strict format before being stored in the database.
In this guide, we will explore Mongoose models, schemas, and data validation techniques with real-world examples.
🛠 Step 1: Understanding Mongoose Models and Schemas
🔹 What is a Schema?
A Mongoose schema defines the structure, data types, and validation rules for documents stored in a MongoDB collection. Think of it as a blueprint for how data should be stored.
Example: Defining a User Schema
const mongoose = require("mongoose");
const userSchema = new mongoose.Schema({
name: { type: String, required: true }, // Name is required
age: Number, // Age is optional
email: { type: String, unique: true, required: true } // Email must be unique and required
});
📌 Explanation:
🔹 What is a Model?
A model in Mongoose is an interface to interact with MongoDB collections. It allows us to perform CRUD operations (Create, Read, Update, Delete) on documents.
Example: Creating a Model
const User = mongoose.model("User", userSchema);
📌 Explanation:
🔹 Saving a New Document
Once we have the model, we can create and save new user data to the MongoDB database.
const newUser = new User({
name: "Alice",
age: 25,
email: "alice@example.com"
});
newUser.save()
.then(() => console.log("User saved!"))
.catch(err => console.error("Error:", err));
📌 Key points:
🔹 What happens if we try to save a user without an email?
const invalidUser = new User({ name: "Bob", age: 30 });
invalidUser.save()
.then(() => console.log("User saved!"))
.catch(err => console.error("Error:", err));
Since email is required, this operation will fail, and an error message will be logged.
🛠 Step 2: Data Validation and Schema Design in Mongoose
Mongoose provides built-in and custom validation techniques to enforce data integrity. Let’s explore different ways to validate data before storing it in the database.
🔹 Adding Field Validations
Mongoose allows us to define constraints like:
✅ required - Ensures the field is not empty.
Recommended by LinkedIn
✅ minlength & maxlength - Sets character length limits for strings.
✅ match - Uses regex patterns for format validation.
✅ enum - Limits values to a predefined set.
✅ min & max - Defines numerical range constraints.
Example: Validating User Schema
const userSchema = new mongoose.Schema({
name: { type: String, required: true, minlength: 3 }, // Minimum length of 3 characters
email: { type: String, required: true, match: /.+\@.+\..+/ }, // Must match an email pattern
age: { type: Number, min: 18, max: 65 }, // Age must be between 18 and 65
role: { type: String, enum: ["admin", "user", "guest"], default: "user" } // Role can only be admin, user, or guest
});
📌 Key Takeaways:
✔ required: true ensures the field is not empty.
✔ minlength: 3 ensures names have at least 3 characters.
✔ match: /.+\@.+\..+/ ensures the email follows a proper format.
✔ min: 18, max: 65 ensures age is within the allowed range.
✔ enum limits the role field to specific values.
🔹 Using Default Values
We can assign default values to fields when they are not provided.
Example: Setting Default Values
const userSchema = new mongoose.Schema({
isActive: { type: Boolean, default: true }
});
Now, if a user document is created without specifying isActive, it will automatically be set to true.
🔹 Custom Validation
For advanced cases, we can write custom validation functions.
Example: Custom Age Validation
const userSchema = new mongoose.Schema({
age: {
type: Number,
validate: {
validator: function(value) {
return value >= 18;
},
message: "Age must be at least 18."
}
}
});
📌 How it works:
✔ The validator function checks if age >= 18.
✔ If validation fails, the custom error message is returned.
🔹 Pre-save Hooks (Middleware)
Mongoose allows us to run functions before saving documents using middleware.
Example: Hashing Passwords Before Saving
const bcrypt = require("bcrypt");
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
password: { type: String, required: true }
});
userSchema.pre("save", async function (next) {
if (!this.isModified("password")) return next();
this.password = await bcrypt.hash(this.password, 10);
next();
});
📌 Why use this?
✔ Ensures that passwords are hashed before being stored in the database.
✔ Prevents plain-text password storage, improving security.
Jr. UI/UX design and development | Figma |HTML & CSS | Wordpress Developer | Graphic Designer | Web Designer
2moVery informative