MongoDB with Node.js and Mongoose

intermediate
15 min

MongoDB with Node.js and Mongoose

So far we have driven MongoDB from the shell. Real applications talk to it through a driver, and in the Node.js world most teams add Mongoose, an object-document mapper (ODM) that brings schemas, validation, and middleware to your models. In this CodeYourCraft lesson you will connect to MongoDB from Node.js, define a Mongoose schema, and build the CRUD operations behind a small products API.

Setting Up the Project

bash
mkdir shop-api && cd shop-api npm init -y npm install mongoose dotenv

Put your connection string in a .env file so it never lands in version control:

text
MONGODB_URI=mongodb+srv://appuser:secret@cluster0.abc12.mongodb.net/shop

Connecting to the Database

javascript
// db.js require('dotenv').config() const mongoose = require('mongoose') async function connectDB() { try { await mongoose.connect(process.env.MONGODB_URI) console.log('MongoDB connected') } catch (err) { console.error('Connection failed:', err.message) process.exit(1) } } module.exports = connectDB

Mongoose manages a connection pool for you, so you connect once at startup and reuse it everywhere.

Defining a Schema and Model

A Mongoose schema declares the shape, types, defaults, and validation rules of documents in a collection. A model wraps the schema with query methods:

javascript
// models/Product.js const mongoose = require('mongoose') const productSchema = new mongoose.Schema({ name: { type: String, required: true, trim: true }, price: { type: Number, required: true, min: 0 }, category: { type: String, enum: ['audio', 'video', 'accessories'], index: true }, tags: [String], stock: { type: Number, default: 0 } }, { timestamps: true }) module.exports = mongoose.model('Product', productSchema)

The timestamps option adds createdAt and updatedAt automatically, and Mongoose pluralizes the model name to use the products collection.

CRUD with the Model

javascript
const Product = require('./models/Product') // Create const lamp = await Product.create({ name: 'Desk Lamp', price: 1299, category: 'accessories' }) // Read const cheap = await Product.find({ price: { $lt: 5000 } }) .sort({ price: 1 }) .limit(10) .lean() // plain objects, faster for read-only use // Update await Product.findByIdAndUpdate(lamp._id, { $inc: { stock: 25 } }, { new: true }) // Delete await Product.findByIdAndDelete(lamp._id)

The query syntax is the same MongoDB language you already know from mongosh, which is why we learned the shell first. The lean() call is a favorite performance tip: it skips constructing full Mongoose documents when you only need data to send as JSON.

Validation and Middleware

Schema validation runs before every save, turning bad data into catchable errors instead of corrupt documents:

javascript
try { await Product.create({ name: 'Ghost Item', price: -50 }) } catch (err) { console.log(err.errors.price.message) // below minimum value }

Middleware (hooks) lets you run logic around operations, for example generating a slug before saving:

javascript
productSchema.pre('save', function () { this.slug = this.name.toLowerCase().replace(/\s+/g, '-') })

Driver or Mongoose?

The official mongodb driver is lighter and maps one-to-one to shell commands, which suits microservices and scripts. Mongoose adds schemas, casting, validation, population of references, and hooks, which pay off in larger applications. Both share the same query language underneath, so nothing you have learned is wasted either way.

Key Takeaways

  • Connect once at startup; Mongoose pools connections for the whole app.
  • Schemas define types, defaults, and validation; models expose CRUD methods.
  • Keep connection strings in environment variables via dotenv.
  • Use lean() for read-only queries and timestamps for free audit fields.
  • Mongoose validation and middleware centralize data rules in your models.

To finish the series, the next lesson covers the best practices and security checklist every production MongoDB deployment needs.

MongoDB with Node.js and Mongoose - MongoDB | CodeYourCraft | CodeYourCraft