MongoDB with Next.js
Integrate MongoDB database with your Next.js application
🍃 What is MongoDB?
MongoDB is a popular NoSQL database that stores data in flexible JSON-like documents. It integrates perfectly with Next.js for building scalable applications with dynamic data requirements and complex queries.
// Install MongoDB driver
npm install mongodb
// Basic MongoDB connection
import { MongoClient } from 'mongodb'
const client = new MongoClient(process.env.MONGODB_URI)
await client.connect()
Key MongoDB Concepts
Collections
Groups of related documents
db.collection('users')
.find()
.toArray()
Queries
Find and filter documents easily
db.collection('users')
.find({ age: { $gt: 25 } })
Aggregation
Process and transform data
db.collection('orders')
.aggregate([
{ $group: { _id: "$status" } }
])
🔹 Setting Up MongoDB Connection
Create a reusable MongoDB connection for your Next.js app. This singleton pattern ensures efficient connection pooling and prevents creating multiple database connections across your application.
// lib/mongodb.js
import { MongoClient } from 'mongodb'
const uri = process.env.MONGODB_URI
const options = {}
let client
let clientPromise
if (!process.env.MONGODB_URI) {
throw new Error('Please add your Mongo URI to .env.local')
}
if (process.env.NODE_ENV === 'development') {
if (!global._mongoClientPromise) {
client = new MongoClient(uri, options)
global._mongoClientPromise = client.connect()
}
clientPromise = global._mongoClientPromise
} else {
client = new MongoClient(uri, options)
clientPromise = client.connect()
}
export default clientPromise
Environment Variable (.env.local):
MONGODB_URI=mongodb+srv://username:[email protected]/database
🔹 Fetching Data with API Routes
Create API endpoints to interact with MongoDB. Next.js API routes provide a secure backend layer where you can safely query your database without exposing credentials to the client.
// app/api/users/route.js
import { NextResponse } from 'next/server'
import clientPromise from '@/lib/mongodb'
export async function GET() {
try {
const client = await clientPromise
const db = client.db('myDatabase')
const users = await db
.collection('users')
.find({})
.limit(10)
.toArray()
return NextResponse.json(users)
} catch (error) {
return NextResponse.json(
{ error: 'Failed to fetch users' },
{ status: 500 }
)
}
}
🔹 Displaying Data in Components
Fetch and display MongoDB data in your React components. Use Next.js server components for better performance or client components for interactive features with real-time updates.
// app/users/page.js
'use client'
import { useEffect, useState } from 'react'
export default function UsersPage() {
const [users, setUsers] = useState([])
const [loading, setLoading] = useState(true)
useEffect(() => {
async function fetchUsers() {
const response = await fetch('/api/users')
const data = await response.json()
setUsers(data)
setLoading(false)
}
fetchUsers()
}, [])
if (loading) return <p>Loading...</p>
return (
<div>
<h1>Users</h1>
{users.map(user => (
<div key={user._id}>
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
))}
</div>
)
}
🔹 Creating New Documents
Insert new data into MongoDB collections. The insertOne method adds a single document and returns the inserted ID for immediate use in your application.
// app/api/users/route.js
export async function POST(request) {
try {
const client = await clientPromise
const db = client.db('myDatabase')
const body = await request.json()
const result = await db
.collection('users')
.insertOne({
name: body.name,
email: body.email,
createdAt: new Date()
})
return NextResponse.json({
message: 'User created',
userId: result.insertedId
})
} catch (error) {
return NextResponse.json(
{ error: 'Failed to create user' },
{ status: 500 }
)
}
}
🔹 Updating Documents
Modify existing documents in your MongoDB collection. Use updateOne for single documents or updateMany for bulk updates with flexible query filters.
// app/api/users/[id]/route.js
import { ObjectId } from 'mongodb'
export async function PUT(request, { params }) {
try {
const client = await clientPromise
const db = client.db('myDatabase')
const body = await request.json()
const result = await db
.collection('users')
.updateOne(
{ _id: new ObjectId(params.id) },
{ $set: { name: body.name, email: body.email } }
)
return NextResponse.json({
message: 'User updated',
modifiedCount: result.modifiedCount
})
} catch (error) {
return NextResponse.json(
{ error: 'Failed to update user' },
{ status: 500 }
)
}
}
🔹 Deleting Documents
Remove documents from your MongoDB collection. Always validate user permissions before allowing delete operations to maintain data security and integrity.
// app/api/users/[id]/route.js
export async function DELETE(request, { params }) {
try {
const client = await clientPromise
const db = client.db('myDatabase')
const result = await db
.collection('users')
.deleteOne({ _id: new ObjectId(params.id) })
if (result.deletedCount === 0) {
return NextResponse.json(
{ error: 'User not found' },
{ status: 404 }
)
}
return NextResponse.json({
message: 'User deleted successfully'
})
} catch (error) {
return NextResponse.json(
{ error: 'Failed to delete user' },
{ status: 500 }
)
}
}