Chapter 3.2☕ 18 min read

MongoDB Connection & Schemas — Mongoose Setup

Mongoose is a MongoDB ODM (Object Document Mapper) that makes it easy to connect, model, and validate data in Node.js.

01What is Mongoose? — Node.js ka ORM for MongoDB

Mongoose is an ODM (Object Document Mapper) for MongoDB and Node.js. Think of it as a translator between your Express app and MongoDB — it helps you:

  • Connect — Establish a connection to MongoDB (local or Atlas cloud)
  • Define schemas — Describe what your data looks like (what fields, what types)
  • Validate — Automatically validate data before saving to the database
  • Query — Use simple JavaScript methods to CRUD data
  • Middleware — Run functions before/after saving (like hashing passwords)

Remember in the Express chapter (2.1-2.5), we stored biryani data in in-memory arrays? When the server restarted, all orders were lost. Mongoose + MongoDB fixes that — data persists in the cloud, just like Swiggy's real order database.

Installing Mongoose:

npm install mongoose

That's it. One command and Mongoose is ready to use. Now let's connect to a MongoDB database.

02Connecting to MongoDB Atlas — Cloud se Connection

MongoDB Atlas is MongoDB's cloud database service. It offers a free tier (512MB storage) that's perfect for learning. Instead of running MongoDB on your laptop, Atlas hosts it in the cloud — just like Swiggy doesn't run its database on a single laptop but on cloud servers.

Step 1: Create a free Atlas account

Go to mongodb.com/atlas and sign up for a free account. Create a cluster (M0 free tier) and get your connection string.

Step 2: Get your connection string

Your connection string looks like this:

mongodb+srv://username:password@cluster0.abcde.mongodb.net/swiggy-db?retryWrites=true&w=majority

Step 3: Connect using Mongoose

// db.js — MongoDB Connection
import mongoose from 'mongoose';

const connectDB = async () => {
  try {
    const conn = await mongoose.connect(process.env.MONGO_URI);
    console.log('MongoDB connected: ' + conn.connection.host);
  } catch (error) {
    console.error('Connection failed: ' + error.message);
    process.exit(1);
  }
};

export default connectDB;

Step 4: Call the connection in server.js

// server.js — Connect to MongoDB on startup
import express from 'express';
import connectDB from './config/db.js';

const app = express();

// Connect to MongoDB before starting the server
connectDB();

// Middleware
app.use(express.json());

// Routes
app.get('/', (req, res) => {
  res.json({ message: 'Swiggy Backend — MongoDB Connected!' });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log('Server running on port ' + PORT);
});

Connection events you should know:

  • mongoose.connection.on('connected') — Fires when connected successfully
  • mongoose.connection.on('error') — Fires on connection error
  • mongoose.connection.on('disconnected') — Fires when connection is lost

Pro tip: Always add connection error handling. If MongoDB goes down, your API should respond gracefully instead of crashing.

03Creating a Mongoose Schema — Biryani Order Schema

A Schema in Mongoose defines the structure of your documents — what fields they have, what data types, and what validation rules apply. Think of it as a blueprint for your data.

Creating a Biryani Order Schema:

// models/Biryani.js — Biryani Order Schema
import mongoose from 'mongoose';

const biryaniSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, 'Biryani ka naam to batao bhai!'],
    trim: true,
    minlength: [3, 'Itna chota naam? Kya biryani hai yeh?']
  },
  restaurant: {
    type: String,
    required: [true, 'Kaunsa restaurant ka biryani hai?'],
    trim: true
  },
  price: {
    type: Number,
    required: [true, 'Price to batao — free mein thodi degi Swiggy?'],
    min: [1, 'Itna sasta biryani? Kahan milta hai?']
  },
  category: {
    type: String,
    enum: ['Chicken', 'Mutton', 'Veg', 'Fish', 'Beef'],
    default: 'Chicken'
  },
  spicyLevel: {
    type: String,
    enum: ['Low', 'Medium', 'High', 'Extra High'],
    default: 'Medium'
  },
  isAvailable: {
    type: Boolean,
    default: true
  },
  description: {
    type: String,
    maxlength: [500, 'Itna bada description? Essay nahi likhna bhai!'],
    default: ''
  },
  rating: {
    type: Number,
    min: 0,
    max: 5,
    default: 3.5
  },
  ingredients: [{
    name: String,
    quantity: String
  }]
}, {
  timestamps: true  // Automatically adds createdAt and updatedAt
});

Schema Types in Mongoose:

TypeDescriptionExample
StringText data'Chicken Biryani'
NumberNumeric values250
Booleantrue/falsetrue
DateDate/timestampnew Date()
ArrayList of items['rice', 'chicken']
ObjectIdReference to another documentmongoose.Types.ObjectId
MixedAny data type{ anyField: 'anything' }
04Creating a Model — Schema se Model tak

A Model is a compiled version of your Schema. It gives you methods to actually query, create, update, and delete documents in MongoDB. If the Schema is the blueprint, the Model is the factory that produces objects from that blueprint.

// models/Biryani.js — Full Schema + Model
import mongoose from 'mongoose';

const biryaniSchema = new mongoose.Schema({
  name: { type: String, required: true, trim: true },
  restaurant: { type: String, required: true },
  price: { type: Number, required: true, min: 1 },
  category: {
    type: String,
    enum: ['Chicken', 'Mutton', 'Veg', 'Fish'],
    default: 'Chicken'
  },
  isAvailable: { type: Boolean, default: true },
  rating: { type: Number, default: 3.5 }
}, { timestamps: true });

// Create the Model from the Schema
const Biryani = mongoose.model('Biryani', biryaniSchema);

export default Biryani;

Using the Model in your routes:

// routes/biryani.routes.js
import express from 'express';
import Biryani from '../models/Biryani.js';

const router = express.Router();

// Create a new biryani
router.post('/', async (req, res) => {
  try {
    const biryani = await Biryani.create(req.body);
    res.status(201).json({ success: true, data: biryani });
  } catch (error) {
    res.status(400).json({ success: false, message: error.message });
  }
});

// Get all biryanis
router.get('/', async (req, res) => {
  try {
    const biryanis = await Biryani.find({});
    res.json({ success: true, count: biryanis.length, data: biryanis });
  } catch (error) {
    res.status(500).json({ success: false, message: error.message });
  }
});

export default router;

Important: Mongoose automatically pluralizes and lowercases your model name to create the MongoDB collection. mongoose.model('Biryani', biryaniSchema) creates a collection called biryanis.

The first argument to mongoose.model() is the singular name (e.g., 'Biryani'). The collection name becomes 'biryanis' (plural, lowercase). You can override this with the collection option in the schema.

05Environment Variables — .env mein DB URI Store Karna

Hardcoding your MongoDB connection string in your code is like writing your Swiggy password on a napkin and leaving it on the restaurant counter. Never hardcode secrets!

Step 1: Create a .env file

# .env — Environment Variables
MONGO_URI=mongodb+srv://username:password@cluster0.abcde.mongodb.net/swiggy-db?retryWrites=true&w=majority
PORT=3000
NODE_ENV=development

Step 2: Install dotenv

npm install dotenv

Step 3: Load .env in your app

// server.js — With Environment Variables
import 'dotenv/config';
import express from 'express';
import connectDB from './config/db.js';

const app = express();

// Connect to MongoDB using URI from .env
connectDB();

app.use(express.json());

app.listen(process.env.PORT || 3000, () => {
  console.log('Server running in ' + process.env.NODE_ENV + ' mode on port ' + process.env.PORT);
});

Step 4: Update db.js to use .env

// config/db.js — Using MONGO_URI from environment
import mongoose from 'mongoose';

const connectDB = async () => {
  try {
    const conn = await mongoose.connect(process.env.MONGO_URI);
    console.log('MongoDB Connected: ' + conn.connection.host);
  } catch (error) {
    console.error('Error: ' + error.message);
    process.exit(1);
  }
};

export default connectDB;

Why .env matters:

  • Security — Your database credentials stay out of your code repository
  • Portability — Different environments (dev, staging, production) use different .env files
  • Configurability — Change database, port, or settings without touching code
  • Team safety — Add .env to .gitignore so no one accidentally commits it

Pro tip: Create a .env.example file in your repo with placeholder values so new developers know what variables they need to set.

Key Takeaways

  • ✅ Mongoose is an ODM (Object Document Mapper) that connects Express to MongoDB
  • ✅ mongoose.connect() connects to MongoDB Atlas using a connection string from .env
  • ✅ Schema defines document structure: field names, types, validation rules, defaults
  • ✅ Model is the compiled schema — use it to query/create/update/delete documents
  • ✅ mongoose.model("Biryani") creates a collection called "biryanis" (plural, lowercase)
  • ✅ Always use .env for MONGO_URI — never hardcode database credentials
  • ✅ Add timestamps: true to get createdAt and updatedAt automatically
  • ✅ Schema validation (required, min, enum, etc.) catches bad data before it reaches the DB
Course Search
Search across all chapters & stages
📖

Search the course

Type any topic — branching, stash, rebase, hooks — and jump straight to that chapter.

merge branchesgit stashundo commitrebase