Section 5: Programming
π’ MongoDB with Node.js
Complete tutorial on using MongoDB with Node.js - CRUD, async/await, Express integration
2
Drivers
CRUD
Full Operations
Express
REST API
Async
Modern JS
Setup & Installation
Get started with MongoDB Node.js driver
Install MongoDB Driver
Terminal
# Initialize project npm init -y # Install MongoDB driver npm install mongodb # Optional: Install dotenv for environment variables npm install dotenv
π‘ Package Versions
This tutorial uses MongoDB driver v6.x with modern async/await syntax. Requires Node.js 14+.
Project Structure
Project Layout
myproject/ βββ package.json βββ .env βββ config/ β βββ db.js βββ models/ β βββ User.js βββ routes/ β βββ users.js βββ server.js
Connecting to MongoDB
Establish database connection
Basic Connection
db.js
const { MongoClient } = require('mongodb'); // Connection string // Local: 'mongodb://localhost:27017' // Atlas: 'mongodb+srv://user:pass@cluster0.mongodb.net/' const uri = 'mongodb://localhost:27017'; const client = new MongoClient(uri); async function connectDB() { try { // Connect to MongoDB await client.connect(); // Verify connection await client.db('admin').command({ ping: 1 }); console.log('β Connected to MongoDB!'); // Get database const db = client.db('myapp'); return db; } catch (error) { console.error('MongoDB connection error:', error); process.exit(1); } } async function closeDB() { await client.close(); console.log('MongoDB connection closed'); } module.exports = { connectDB, closeDB };
Environment Variables
.env
MONGODB_URI=mongodb://localhost:27017 DB_NAME=myapp PORT=3000
Updated db.js
require('dotenv').config(); const { MongoClient } = require('mongodb'); const uri = process.env.MONGODB_URI; const dbName = process.env.DB_NAME; // Rest of the code...
CRUD Operations
Create, Read, Update, Delete with async/await
Insert Documents
Insert Operations
const { connectDB } = require('./config/db'); // Insert One async function insertOne() { const db = await connectDB(); const collection = db.collection('users'); const user = { name: 'Alice Johnson', email: 'alice@example.com', age: 28, active: true, createdAt: new Date() }; const result = await collection.insertOne(user); console.log(`Inserted ID: ${result.insertedId}`); } // Insert Many async function insertMany() { const db = await connectDB(); const collection = db.collection('users'); const users = [ { name: 'Bob Smith', email: 'bob@example.com', age: 35, active: true }, { name: 'Carol White', email: 'carol@example.com', age: 42, active: false }, { name: 'David Brown', email: 'david@example.com', age: 29, active: true } ]; const result = await collection.insertMany(users); console.log(`Inserted ${result.insertedCount} documents`); }
Find Documents
Find Operations
// Find One async function findOne() { const db = await connectDB(); const collection = db.collection('users'); const user = await collection.findOne({ email: 'alice@example.com' }); console.log('Found user:', user); } // Find Many async function findMany() { const db = await connectDB(); const collection = db.collection('users'); // Find active users, sort by name, limit 10 const users = await collection .find({ active: true }) .sort({ name: 1 }) .limit(10) .toArray(); console.log(`Found ${users.length} users`); users.forEach(user => { console.log(` - ${user.name} (${user.email})`); }); } // Complex Query async function complexQuery() { const db = await connectDB(); const collection = db.collection('users'); // Age between 25 and 40, and active const users = await collection.find({ age: { $gte: 25, $lte: 40 }, active: true }).toArray(); console.log('Users between 25-40:', users); }
π‘ Query Operators
$eq- Equal to$gt, $gte- Greater than (or equal)$lt, $lte- Less than (or equal)$in- Matches any value in array$and, $or- Logical operators$regex- Regular expression match
Update Documents
Update Operations
// Update One async function updateOne() { const db = await connectDB(); const collection = db.collection('users'); const result = await collection.updateOne( { email: 'alice@example.com' }, { $set: { age: 29, updatedAt: new Date() } } ); console.log(`Matched: ${result.matchedCount}`); console.log(`Modified: ${result.modifiedCount}`); } // Update Many async function updateMany() { const db = await connectDB(); const collection = db.collection('users'); // Activate all inactive users const result = await collection.updateMany( { active: false }, { $set: { active: true } } ); console.log(`Updated ${result.modifiedCount} documents`); } // Increment Value async function incrementAge() { const db = await connectDB(); const collection = db.collection('users'); await collection.updateOne( { email: 'alice@example.com' }, { $inc: { age: 1 } } // Increment by 1 ); }
Delete Documents
Delete Operations
// Delete One async function deleteOne() { const db = await connectDB(); const collection = db.collection('users'); const result = await collection.deleteOne({ email: 'alice@example.com' }); console.log(`Deleted ${result.deletedCount} document`); } // Delete Many async function deleteMany() { const db = await connectDB(); const collection = db.collection('users'); // Delete users older than 50 const result = await collection.deleteMany({ age: { $gt: 50 } }); console.log(`Deleted ${result.deletedCount} documents`); }
Express REST API
Build a complete API with Express
Install Express
Terminal
npm install express
Server Setup
server.js
require('dotenv').config(); const express = require('express'); const { connectDB } = require('./config/db'); const usersRouter = require('./routes/users'); const app = express(); const PORT = process.env.PORT || 3000; // Middleware app.use(express.json()); // Connect to MongoDB let db; connectDB().then(database => { db = database; // Make db available to routes app.use((req, res, next) => { req.db = db; next(); }); // Routes app.use('/api/users', usersRouter); // Start server app.listen(PORT, () => { console.log(`π Server running on port ${PORT}`); }); });
User Routes
routes/users.js
const express = require('express'); const { ObjectId } = require('mongodb'); const router = express.Router(); // GET all users router.get('/', async (req, res) => { try { const users = await req.db .collection('users') .find() .toArray(); res.json(users); } catch (error) { res.status(500).json({ error: error.message }); } }); // GET user by ID router.get('/:id', async (req, res) => { try { const user = await req.db .collection('users') .findOne({ _id: new ObjectId(req.params.id) }); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json(user); } catch (error) { res.status(500).json({ error: error.message }); } }); // POST create user router.post('/', async (req, res) => { try { const user = { ...req.body, createdAt: new Date() }; const result = await req.db .collection('users') .insertOne(user); res.status(201).json({ _id: result.insertedId, ...user }); } catch (error) { res.status(500).json({ error: error.message }); } }); // PUT update user router.put('/:id', async (req, res) => { try { const result = await req.db .collection('users') .updateOne( { _id: new ObjectId(req.params.id) }, { $set: { ...req.body, updatedAt: new Date() } } ); if (result.matchedCount === 0) { return res.status(404).json({ error: 'User not found' }); } res.json({ message: 'User updated' }); } catch (error) { res.status(500).json({ error: error.message }); } }); // DELETE user router.delete('/:id', async (req, res) => { try { const result = await req.db .collection('users') .deleteOne({ _id: new ObjectId(req.params.id) }); if (result.deletedCount === 0) { return res.status(404).json({ error: 'User not found' }); } res.json({ message: 'User deleted' }); } catch (error) { res.status(500).json({ error: error.message }); } }); module.exports = router;
β
API Endpoints Ready!
GET /api/users- Get all usersGET /api/users/:id- Get user by IDPOST /api/users- Create userPUT /api/users/:id- Update userDELETE /api/users/:id- Delete user
Mongoose ODM
Object Data Modeling for MongoDB
Install Mongoose
Terminal
npm install mongoose
Connection & Schema
models/User.js
const mongoose = require('mongoose'); // Define Schema const userSchema = new mongoose.Schema({ name: { type: String, required: true, trim: true }, email: { type: String, required: true, unique: true, lowercase: true }, age: { type: Number, min: 0, max: 120 }, active: { type: Boolean, default: true } }, { timestamps: true // Adds createdAt, updatedAt }); // Create Model const User = mongoose.model('User', userSchema); module.exports = User;
Mongoose CRUD
Using Mongoose
const User = require('./models/User'); // Create const user = new User({ name: 'Alice Johnson', email: 'alice@example.com', age: 28 }); await user.save(); // OR using create await User.create({ name: 'Bob Smith', email: 'bob@example.com', age: 35 }); // Find const users = await User.find({ active: true }); const user = await User.findOne({ email: 'alice@example.com' }); const user = await User.findById(id); // Update await User.updateOne( { email: 'alice@example.com' }, { $set: { age: 29 } } ); await User.findByIdAndUpdate(id, { age: 30 }); // Delete await User.deleteOne({ email: 'alice@example.com' }); await User.findByIdAndDelete(id);
π‘ Mongoose Benefits
- Schema validation
- Type casting
- Middleware (hooks)
- Virtual properties
- Built-in validation
- Cleaner syntax
Aggregation Pipeline
Complex data operations
Basic Aggregation
Aggregation Example
async function aggregation() { const db = await connectDB(); const collection = db.collection('users'); const result = await collection.aggregate([ // Match: age >= 25 { $match: { age: { $gte: 25 } } }, // Group by active status { $group: { _id: '$active', count: { $sum: 1 }, avgAge: { $avg: '$age' } } }, // Sort by count descending { $sort: { count: -1 } } ]).toArray(); console.log(result); }
Best Practices
Production-ready code
Connection Management
β οΈ Important Tips
- Reuse Client: Create one client, reuse across app
- Use Async/Await: Cleaner than callbacks
- Error Handling: Always use try/catch
- Environment Variables: Never hardcode credentials
- Indexes: Create indexes for frequently queried fields
- Connection Pool: Driver handles pooling automatically