Mean 07 Mongoose Crud
title: "Mongoose CRUD Operations — Create, Read, Update, Delete Documents" description: "Learn Mongoose CRUD operations for the MEAN Stack: create, read, update, and delete MongoDB documents with filtering, sorting, pagination, and aggregation." weight: 17 date: 2026-06-28 lastmod: 2026-06-28 tags: [frameworks, mean]
Mongoose provides a comprehensive API for CRUD operations on MongoDB documents, including filtering, sorting, pagination, and aggregation.
What You'll Learn
You will master Mongoose CRUD operations including create, read with filtering and pagination, update with various methods, and delete with safety checks.
Why It Matters
CRUD operations are the foundation of any data-driven application. Understanding Mongoose's CRUD API enables building robust REST endpoints.
Real-World Use
Durga Antivirus Pro uses Mongoose CRUD operations for managing threat databases with complex filtering and pagination for the admin dashboard.
flowchart LR
A[CRUD Operations] --> B[Create]
A --> C[Read]
A --> D[Update]
A --> E[Delete]
B --> F[create, save]
C --> G[find, findById, findOne]
D --> H[updateOne, findByIdAndUpdate]
E --> I[deleteOne, findByIdAndDelete]
style A fill:#4a90d9,color:#fff
Create Operations
Two primary ways to create documents.
const User = require('../models/User');
// Method 1: Create and save separately
const user = new User({
name: 'Bob',
email: 'bob@example.com',
age: 25
});
await user.save();
// Method 2: Create in one step
const newUser = await User.create({
name: 'Charlie',
email: 'charlie@example.com',
age: 35
});
// Method 3: Create multiple documents
const users = await User.insertMany([
{ name: 'Diana', email: 'diana@example.com' },
{ name: 'Eve', email: 'eve@example.com' }
]);
Expected output: Users are created in the MongoDB users collection. save() returns the saved document. create() creates and saves in one step. insertMany() creates multiple documents in a single operation.
Read Operations
Various ways to read documents.
// Find all documents
const allUsers = await User.find();
// Find with filters
const adults = await User.find({ age: { $gte: 18 } });
const byName = await User.find({ name: /^A/ }); // Regex: names starting with A
// Find single document
const byId = await User.findById('665abc...');
const byEmail = await User.findOne({ email: 'alice@example.com' });
// Field selection
const namesOnly = await User.find().select('name email -_id');
// Sorting
const sorted = await User.find().sort({ age: -1, name: 1 });
// Pagination
const page = 2;
const limit = 10;
const paginated = await User.find()
.skip((page - 1) * limit)
.limit(limit)
.sort({ createdAt: -1 });
// Count
const total = await User.countDocuments({ age: { $gte: 18 } });
Expected output: Flexible reading with filtering, field selection, sorting, pagination, and counting. Each method returns documents matching the criteria.
Update Operations
Multiple ways to update documents.
// Update one document by filter
await User.updateOne(
{ email: 'bob@example.com' },
{ $set: { age: 26, role: 'admin' } }
);
// Find and update (returns old document by default)
const oldUser = await User.findByIdAndUpdate(
id,
{ $set: { name: 'Robert' } }
);
// Find and update (returns new document)
const updatedUser = await User.findByIdAndUpdate(
id,
{ $inc: { age: 1 } },
{ new: true }
);
// Update multiple documents
await User.updateMany(
{ role: 'user' },
{ $set: { permissions: ['read'] } }
);
// Replace entire document
await User.replaceOne(
{ email: 'old@example.com' },
{ name: 'New Name', email: 'new@example.com' }
);
Expected output: Update operations modify documents. $set updates specific fields. $increments numbers. updateMany affects all matching documents. replaceOne replaces the entire document.
Delete Operations
Safe deletion of documents.
// Delete one document by filter
const result = await User.deleteOne({ email: 'bob@example.com' });
console.log(result.deletedCount); // 1 if deleted, 0 if not found
// Delete by ID
const deleted = await User.findByIdAndDelete(id);
// Delete multiple documents
await User.deleteMany({ active: false });
// Delete all documents (use with caution)
// await User.deleteMany({});
Expected output: deleteOne removes the first matching document. findByIdAndDelete removes by ID and returns the deleted document. deleteMany removes all matching documents.
Aggregation Pipeline
Use MongoDB's aggregation framework for complex data processing.
const stats = await User.aggregate([
// Stage 1: Filter active users
{ $match: { active: true } },
// Stage 2: Group by role and calculate stats
{
$group: {
_id: '$role',
count: { $sum: 1 },
avgAge: { $avg: '$age' },
minAge: { $min: '$age' },
maxAge: { $max: '$age' }
}
},
// Stage 3: Sort by count descending
{ $sort: { count: -1 } }
]);
Expected output: An array of objects with role, count, average age, and age range. Aggregation pipelines process documents through sequential stages.
Common Mistakes
Not handling empty results: find() returns an empty array if nothing matches. findOne() returns null. Always check before accessing properties.
Using findByIdAndUpdate without { new: true }: The returned document is the pre-update version. Use { new: true } for the updated version.
Not limiting results for list endpoints: Without limit, find() returns all documents. Always implement pagination for list endpoints.
Forgetting to await: Mongoose operations are async. Missing await returns a Query object, not the actual data.
Using $set unnecessarily for single field updates: User.age = 30 followed by user.save() is simpler than User.updateOne() for individual field updates.
Practice Questions
- What is the difference between save() and create()?
save() is called on an existing document instance. create() is a static method that creates and saves in one step.
- How do you paginate results with Mongoose?
Use skip() and limit() on the query. skip((page-1)*limit) skips previous pages. limit() sets page size.
- What does { new: true } do in findByIdAndUpdate?
It returns the updated document instead of the original pre-update document.
- What is the aggregation pipeline used for?
Processing documents through sequential stages for complex data analysis, grouping, and transformations.
- How do you check if a delete operation removed any documents?
Check result.deletedCount from deleteOne or deleteMany result.
Challenge
Build a complete CRUD API for products with: create (with validation), list (with pagination, sorting by price, filtering by category), read by ID, update (partial update), delete (with safety check), and an aggregation endpoint for category statistics.
Frequently Asked Questions
Mini Project
Build a CRUD API for a task manager with: create task (title, description, priority, status), list tasks (filter by status, sort by priority, paginate), update task status, delete task, and an aggregation endpoint for task statistics by priority.
What's Next
Learn to expose CRUD operations through REST API Routes in Express.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro