TrueSpec

MongoDB CRUD with Mongoose

Schema validation, virtuals, populate, indexes, and aggregation

What You’ll Build

After following this guide, you will have a working implementation of mongodb crud with mongoose in your project. Build a complete MongoDB data layer with Mongoose. Covers schema design with validation, virtual fields, populating references (joins), indexing for performance, and aggregation pipelines for analytics queries.

Use Cases & Problems Solved

  • Set up a production-ready database layer with type-safe queries
  • Manage schema changes through migrations without data loss
  • Avoid raw SQL injection risks and inconsistent data access patterns

Prerequisites

  • MongoDB running locally or MongoDB Atlas connection string
  • Node.js 18+

Step-by-Step Implementation

Install and connect

The following snippet shows how to install and connect. Copy this into your project and adjust the values for your environment.

const mongoose = require('mongoose');

mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/myapp')
  .then(() => console.log('Connected to MongoDB'))
  .catch(err => console.error('Connection error:', err));

Define schema with validation

The following snippet shows how to define schema with validation. Copy this into your project and adjust the values for your environment.

const userSchema = new mongoose.Schema({
  email: { type: String, required: true, unique: true, lowercase: true,
    match: [/^\S+@\S+\.\S+$/, 'Invalid email format'] },
  name: { type: String, required: true, minlength: 2 },
  role: { type: String, enum: ['user', 'admin'], default: 'user' },
  posts: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Post' }],
}, { timestamps: true });

// Virtual field
userSchema.virtual('postCount').get(function() {
  return this.posts.length;
});

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

CRUD with populate

The following snippet shows how to crud with populate. Copy this into your project and adjust the values for your environment.

// Create
const user = await User.create({ email: 'bob@test.com', name: 'Bob' });

// Read with populated references
const userWithPosts = await User.findById(userId).populate('posts');

// Update
await User.findByIdAndUpdate(userId, { name: 'Robert' }, { new: true, runValidators: true });

// Delete
await User.findByIdAndDelete(userId);

// Aggregation
const stats = await User.aggregate([
  { $group: { _id: '$role', count: { $sum: 1 } } },
]);

⚠️ Don’t Do This

❌ Forgetting to add indexes on fields you query frequently

// Slow! Full collection scan on every query
const user = await User.findOne({ email: 'bob@test.com' });

✅ Add indexes for frequently queried fields

const userSchema = new mongoose.Schema({
  email: { type: String, unique: true, index: true }, // indexed!
  name: String,
});
// Or: userSchema.index({ email: 1, createdAt: -1 }); // compound index

Testing

Verify your implementation with these tests:

// __tests__/mongodb-crud-with-mongoose.test.ts
import { describe, it, expect } from 'vitest';

describe('MongoDB CRUD with Mongoose', () => {
  it('should initialize without errors', () => {
    // Test that the setup completes successfully
    expect(() => setup()).not.toThrow();
  });

  it('should handle the primary use case', async () => {
    const result = await execute();
    expect(result).toBeDefined();
    expect(result.success).toBe(true);
  });

  it('should handle edge cases', async () => {
    // Test with empty/null input
    const result = await execute(null);
    expect(result.error).toBeDefined();
  });
});

Verification

node app.js
# Check MongoDB for documents:
mongosh
> use myapp
> db.users.find().pretty()

Related Specs

Beginner

SQLite for Desktop/Local Apps

better-sqlite3 setup, WAL mode, concurrent access, and performance tuning

Database & ORM
Intermediate

Redis Caching for API Responses

Cache-aside pattern, TTL, invalidation, and cache stampede prevention

Database & ORM
Advanced

Safe Database Migrations

Zero-downtime migration patterns, rollback strategies, and data backfills

Database & ORM