Next.js 中使用 MongoDB 完整指南

1. 安裝依賴

npm install mongodb
# 或者使用 mongoose(ODM)
npm install mongoose

2. 數據庫連接配置

使用原生 MongoDB 驅動

創建 lib/mongodb.js 文件:

import { MongoClient } from 'mongodb'const uri = process.env.MONGODB_URI
const options = {}let client
let clientPromiseif (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

環境變量 .env.local

MONGODB_URI=mongodb://localhost:27017/myapp
# 或者 MongoDB Atlas
MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/database

3. API 路由中的基本操作

創建基礎的數據庫操作函數

創建 lib/db.js

import clientPromise from './mongodb'export async function connectToDatabase() {const client = await clientPromiseconst db = client.db('myapp') // 數據庫名稱return { client, db }
}

4. 增加數據(Create)

插入單條記錄

創建 pages/api/users/create.js

import { connectToDatabase } from '../../../lib/db'export default async function handler(req, res) {if (req.method !== 'POST') {return res.status(405).json({ message: 'Method not allowed' })}try {const { db } = await connectToDatabase()const collection = db.collection('users')// 插入單條記錄const newUser = {name: req.body.name,email: req.body.email,age: req.body.age,createdAt: new Date()}const result = await collection.insertOne(newUser)res.status(201).json({success: true,insertedId: result.insertedId,data: { ...newUser, _id: result.insertedId }})} catch (error) {res.status(500).json({ success: false, error: error.message })}
}

使用示例:

// 前端調用
const createUser = async () => {const response = await fetch('/api/users/create', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({name: 'John Doe',email: 'john@example.com',age: 30})})const result = await response.json()console.log(result)
}

插入多條記錄

創建 pages/api/users/create-many.js

import { connectToDatabase } from '../../../lib/db'export default async function handler(req, res) {if (req.method !== 'POST') {return res.status(405).json({ message: 'Method not allowed' })}try {const { db } = await connectToDatabase()const collection = db.collection('users')// 插入多條記錄const users = req.body.users.map(user => ({...user,createdAt: new Date()}))const result = await collection.insertMany(users)res.status(201).json({success: true,insertedCount: result.insertedCount,insertedIds: result.insertedIds})} catch (error) {res.status(500).json({ success: false, error: error.message })}
}

5. 查詢數據(Read)

查詢所有記錄

創建 pages/api/users/index.js

import { connectToDatabase } from '../../../lib/db'export default async function handler(req, res) {if (req.method !== 'GET') {return res.status(405).json({ message: 'Method not allowed' })}try {const { db } = await connectToDatabase()const collection = db.collection('users')// 查詢所有記錄const users = await collection.find({}).toArray()res.status(200).json({success: true,count: users.length,data: users})} catch (error) {res.status(500).json({ success: false, error: error.message })}
}

查詢單條記錄

創建 pages/api/users/[id].js

import { connectToDatabase } from '../../../lib/db'
import { ObjectId } from 'mongodb'export default async function handler(req, res) {const { id } = req.queryif (req.method === 'GET') {try {const { db } = await connectToDatabase()const collection = db.collection('users')// 通過 _id 查詢單條記錄const user = await collection.findOne({ _id: new ObjectId(id) })if (!user) {return res.status(404).json({ success: false, message: 'User not found' })}res.status(200).json({success: true,data: user})} catch (error) {res.status(500).json({ success: false, error: error.message })}}
}

條件查詢

創建 pages/api/users/search.js

import { connectToDatabase } from '../../../lib/db'export default async function handler(req, res) {if (req.method !== 'GET') {return res.status(405).json({ message: 'Method not allowed' })}try {const { db } = await connectToDatabase()const collection = db.collection('users')const { name, email, minAge, maxAge, page = 1, limit = 10 } = req.query// 構建查詢條件let query = {}// 模糊查詢名稱if (name) {query.name = { $regex: name, $options: 'i' }}// 精確查詢郵箱if (email) {query.email = email}// 年齡范圍查詢if (minAge || maxAge) {query.age = {}if (minAge) query.age.$gte = parseInt(minAge)if (maxAge) query.age.$lte = parseInt(maxAge)}// 分頁const skip = (parseInt(page) - 1) * parseInt(limit)// 執行查詢const users = await collection.find(query).sort({ createdAt: -1 }) // 按創建時間倒序.skip(skip).limit(parseInt(limit)).toArray()// 獲取總數const total = await collection.countDocuments(query)res.status(200).json({success: true,data: users,pagination: {page: parseInt(page),limit: parseInt(limit),total,pages: Math.ceil(total / parseInt(limit))}})} catch (error) {res.status(500).json({ success: false, error: error.message })}
}

查詢特定字段

創建 pages/api/users/names.js

import { connectToDatabase } from '../../../lib/db'export default async function handler(req, res) {if (req.method !== 'GET') {return res.status(405).json({ message: 'Method not allowed' })}try {const { db } = await connectToDatabase()const collection = db.collection('users')// 只查詢 name 和 email 字段,排除 _idconst users = await collection.find({}, { projection: { name: 1, email: 1, _id: 0 } }).toArray()res.status(200).json({success: true,data: users})} catch (error) {res.status(500).json({ success: false, error: error.message })}
}

6. 更新數據(Update)

更新單條記錄

pages/api/users/[id].js 中添加 PUT 方法:

import { connectToDatabase } from '../../../lib/db'
import { ObjectId } from 'mongodb'export default async function handler(req, res) {const { id } = req.queryif (req.method === 'PUT') {try {const { db } = await connectToDatabase()const collection = db.collection('users')const updateData = {...req.body,updatedAt: new Date()}// 移除不能更新的字段delete updateData._iddelete updateData.createdAt// 更新單條記錄const result = await collection.updateOne({ _id: new ObjectId(id) },{ $set: updateData })if (result.matchedCount === 0) {return res.status(404).json({ success: false, message: 'User not found' })}// 返回更新后的數據const updatedUser = await collection.findOne({ _id: new ObjectId(id) })res.status(200).json({success: true,modifiedCount: result.modifiedCount,data: updatedUser})} catch (error) {res.status(500).json({ success: false, error: error.message })}}
}

更新多條記錄

創建 pages/api/users/update-many.js

import { connectToDatabase } from '../../../lib/db'export default async function handler(req, res) {if (req.method !== 'PUT') {return res.status(405).json({ message: 'Method not allowed' })}try {const { db } = await connectToDatabase()const collection = db.collection('users')const { filter, update } = req.body// 批量更新記錄const result = await collection.updateMany(filter,{ $set: {...update,updatedAt: new Date()}})res.status(200).json({success: true,matchedCount: result.matchedCount,modifiedCount: result.modifiedCount})} catch (error) {res.status(500).json({ success: false, error: error.message })}
}

使用示例:

// 將所有年齡小于18的用戶狀態設為未成年
const updateMinors = async () => {const response = await fetch('/api/users/update-many', {method: 'PUT',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({filter: { age: { $lt: 18 } },update: { status: 'minor' }})})const result = await response.json()console.log(result)
}

7. 刪除數據(Delete)

刪除單條記錄

pages/api/users/[id].js 中添加 DELETE 方法:

export default async function handler(req, res) {const { id } = req.queryif (req.method === 'DELETE') {try {const { db } = await connectToDatabase()const collection = db.collection('users')// 刪除單條記錄const result = await collection.deleteOne({ _id: new ObjectId(id) })if (result.deletedCount === 0) {return res.status(404).json({ success: false, message: 'User not found' })}res.status(200).json({success: true,deletedCount: result.deletedCount,message: 'User deleted successfully'})} catch (error) {res.status(500).json({ success: false, error: error.message })}}
}

刪除多條記錄

創建 pages/api/users/delete-many.js

import { connectToDatabase } from '../../../lib/db'export default async function handler(req, res) {if (req.method !== 'DELETE') {return res.status(405).json({ message: 'Method not allowed' })}try {const { db } = await connectToDatabase()const collection = db.collection('users')const { filter } = req.body// 批量刪除記錄const result = await collection.deleteMany(filter)res.status(200).json({success: true,deletedCount: result.deletedCount,message: `${result.deletedCount} users deleted successfully`})} catch (error) {res.status(500).json({ success: false, error: error.message })}
}

8. 高級查詢操作

聚合查詢

創建 pages/api/users/statistics.js

import { connectToDatabase } from '../../../lib/db'export default async function handler(req, res) {if (req.method !== 'GET') {return res.status(405).json({ message: 'Method not allowed' })}try {const { db } = await connectToDatabase()const collection = db.collection('users')// 聚合查詢示例const statistics = await collection.aggregate([{$group: {_id: null,totalUsers: { $sum: 1 },averageAge: { $avg: '$age' },minAge: { $min: '$age' },maxAge: { $max: '$age' }}}]).toArray()// 按年齡分組統計const ageGroups = await collection.aggregate([{$group: {_id: {$switch: {branches: [{ case: { $lt: ['$age', 18] }, then: 'minor' },{ case: { $lt: ['$age', 65] }, then: 'adult' },{ case: { $gte: ['$age', 65] }, then: 'senior' }],default: 'unknown'}},count: { $sum: 1 }}}]).toArray()res.status(200).json({success: true,data: {statistics: statistics[0],ageGroups}})} catch (error) {res.status(500).json({ success: false, error: error.message })}
}

文本搜索

創建 pages/api/users/text-search.js

import { connectToDatabase } from '../../../lib/db'export default async function handler(req, res) {if (req.method !== 'GET') {return res.status(405).json({ message: 'Method not allowed' })}try {const { db } = await connectToDatabase()const collection = db.collection('users')const { q } = req.query // 搜索關鍵詞if (!q) {return res.status(400).json({ success: false, message: 'Search query required' })}// 首先需要創建文本索引// await collection.createIndex({ name: 'text', email: 'text' })// 執行文本搜索const users = await collection.find({ $text: { $search: q } }).sort({ score: { $meta: 'textScore' } }).toArray()res.status(200).json({success: true,query: q,count: users.length,data: users})} catch (error) {res.status(500).json({ success: false, error: error.message })}
}

9. 在組件中使用

React 組件示例

// components/UserList.js
import { useState, useEffect } from 'react'export default function UserList() {const [users, setUsers] = useState([])const [loading, setLoading] = useState(true)const [newUser, setNewUser] = useState({ name: '', email: '', age: '' })// 獲取用戶列表const fetchUsers = async () => {try {const response = await fetch('/api/users')const result = await response.json()if (result.success) {setUsers(result.data)}} catch (error) {console.error('Error fetching users:', error)} finally {setLoading(false)}}// 創建用戶const createUser = async (e) => {e.preventDefault()try {const response = await fetch('/api/users/create', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(newUser)})const result = await response.json()if (result.success) {setUsers([...users, result.data])setNewUser({ name: '', email: '', age: '' })}} catch (error) {console.error('Error creating user:', error)}}// 刪除用戶const deleteUser = async (id) => {if (!confirm('確定要刪除這個用戶嗎?')) returntry {const response = await fetch(`/api/users/${id}`, {method: 'DELETE'})const result = await response.json()if (result.success) {setUsers(users.filter(user => user._id !== id))}} catch (error) {console.error('Error deleting user:', error)}}useEffect(() => {fetchUsers()}, [])if (loading) return <div>Loading...</div>return (<div><h2>User Management</h2>{/* 創建用戶表單 */}<form onSubmit={createUser}><inputtype="text"placeholder="Name"value={newUser.name}onChange={(e) => setNewUser({...newUser, name: e.target.value})}required/><inputtype="email"placeholder="Email"value={newUser.email}onChange={(e) => setNewUser({...newUser, email: e.target.value})}required/><inputtype="number"placeholder="Age"value={newUser.age}onChange={(e) => setNewUser({...newUser, age: parseInt(e.target.value)})}required/><button type="submit">Create User</button></form>{/* 用戶列表 */}<div>{users.map(user => (<div key={user._id} style={{ border: '1px solid #ccc', margin: '10px', padding: '10px' }}><h3>{user.name}</h3><p>Email: {user.email}</p><p>Age: {user.age}</p><button onClick={() => deleteUser(user._id)}>Delete</button></div>))}</div></div>)
}

10. 錯誤處理和最佳實踐

統一錯誤處理

創建 lib/errorHandler.js

export function handleApiError(error, res) {console.error('API Error:', error)if (error.name === 'MongoServerError') {if (error.code === 11000) {// 重復鍵錯誤return res.status(400).json({success: false,error: 'Duplicate key error',details: error.keyValue})}}if (error.name === 'CastError') {// ObjectId 格式錯誤return res.status(400).json({success: false,error: 'Invalid ID format'})}// 通用錯誤return res.status(500).json({success: false,error: 'Internal server error'})
}

數據驗證

創建 lib/validation.js

export function validateUser(userData) {const errors = []if (!userData.name || userData.name.trim().length < 2) {errors.push('Name must be at least 2 characters long')}if (!userData.email || !isValidEmail(userData.email)) {errors.push('Valid email is required')}if (!userData.age || userData.age < 0 || userData.age > 150) {errors.push('Age must be between 0 and 150')}return {isValid: errors.length === 0,errors}
}function isValidEmail(email) {const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/return emailRegex.test(email)
}

這個完整指南涵蓋了 Next.js 中使用 MongoDB 的所有基本操作,包括:

  1. 數據庫連接配置 - 如何正確配置和管理數據庫連接
  2. 增刪改查操作 - 完整的 CRUD 操作示例
  3. 條件查詢 - 各種查詢條件和過濾器的使用
  4. 字段選擇 - 如何只查詢需要的字段
  5. 分頁和排序 - 處理大量數據的最佳實踐
  6. 聚合查詢 - 復雜的數據統計和分析
  7. 錯誤處理 - 統一的錯誤處理機制
  8. 前端集成 - 在 React 組件中如何使用這些 API

每個示例都包含了詳細的注釋說明,可以根據實際需求進行修改和擴展。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/93829.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/93829.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/93829.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

嵌入式系統教學范式演進:云端仿真平臺如何重構溫濕度監測實驗教學

在嵌入式系統開發的教學中&#xff0c;環境溫濕度監測實驗是經典的入門項目。它涉及傳感器原理、外設驅動、數據采集和通信協議等核心知識點。然而傳統實驗模式面臨硬件成本高、調試周期長、設備易損壞等痛點。學生往往因接線錯誤或代碼bug導致傳感器或開發板燒毀&#xff0c;不…

1.6萬 Star 的流行容器云平臺停止開源

什么是 KubeSphere &#xff1f; KubeSphere 是面向云原生應用的容器混合云。 KubeSphere 愿景是打造一個以 Kubernetes 為內核的云原生分布式操作系統&#xff0c;它的架構可以非常方便地使第三方應用與云原生生態組件進行即插即用&#xff08;plug-and-play&#xff09;的集成…

廣東省省考備考(第六十三天8.1)——資料分析、數量(強化訓練)

資料分析 錯題解析解析解析今日題目正確率&#xff1a;80% 數量關系&#xff1a;數學運算 錯題解析解析標記題解析解析解析今日題目正確率&#xff1a;87%

Agents-SDK智能體開發[3]之多Agent執行流程

文章目錄說明Agents SDK基礎Handoffs功能實現Handoffs簡單示例&#x1f31f; 運行結果整理&#x1f4dd; 執行過程概述&#x1f4cb; 運行結果事件一&#xff1a;分診智能體創建轉交請求事件事件二&#xff1a;轉交響應事件事件三&#xff1a;目標 Agent 響應請求并完成任務改進…

深度揭秘端口映射:原理、場景、路由映射故障,與內網IP端口映射外網工具的選擇

內網設備連不上外網&#xff1f;本地網絡如何設置端口映射提供互聯網服務&#xff1f;路由器端口映射失敗怎么辦&#xff1f;沒有公網IP如何做端口映射&#xff1f;在網絡通信領域&#xff0c;端口映射是一項至關重要的技術。在內部網絡環境中&#xff0c;每一臺設備都被分配了…

協作機器人掀起工廠革命:碼垛場景如何用數據重塑制造業命脈?

在長三角某食品包裝工廠的深夜生產線上&#xff0c;大視協作碼垛機器人正在有序碼垛&#xff0c;動作比碼垛老師傅更精準。系統推送的實時能耗報表直接顯示在廠長手機上&#xff0c;整廠能耗同比下降約32%。這不是魔法&#xff0c;這是"一切數據業務化、業務數據化"在…

LeetCode 刷題【24. 兩兩交換鏈表中的節點、25. K 個一組翻轉鏈表】

24. 兩兩交換鏈表中的節點 自己做 解&#xff1a;直接置換 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(i…

多線程向設備發送數據

需求:做一個部門授權&#xff0c;可以把所選擇部門下面的所有人的人臉信息傳到設備組里(多個設備)&#xff0c;問題在于圖片是通過Base64處理之后的&#xff0c;會導致文件名非常長&#xff0c;如果一次性傳很多數據就會超過設備的最長請求長度&#xff0c;如果不用Base64處理的…

Buck的Loadline和DVS區別和聯系

Buck 電路設計中&#xff0c;有兩個概念&#xff0c;一個是Load-Line&#xff0c;一個是DVS&#xff0c;它們的含義是什么呢。 Load-Line&#xff08;也稱為有源電壓定位&#xff0c;AVP&#xff09;是通過調整BUCK電路的輸出電壓&#xff0c;使其根據負載電流動態變化的技術。…

MySQL會話連接數消耗內存分析

關于連接數消耗內存情況 FROM DEEPSEEK 在 MySQL 中&#xff0c;每個單獨的空閑連接所消耗的內存量取決于多個因素&#xff0c;包括連接的線程棧大小&#xff08;由 thread_stack 參數設置&#xff09;和其他每個連接的緩沖區。根據測試結果來看&#xff0c;對于空閑連接的內…

Objective-C實現調節筆記本屏幕亮度(附完整源碼)

Objective-C實現調節筆記本屏幕亮度 在macOS上,您可以使用Objective-C來調節筆記本的屏幕亮度。以下是一個簡單的示例,演示如何使用CoreGraphics框架來實現這一功能。請確保您的Xcode項目中包含CoreGraphics框架。 完整源碼示例 #import <Cocoa/Cocoa.h> #import <…

三十一、【Linux網站服務器】搭建httpd服務器演示個人主頁、用戶認證、https加密網站配置

httpd服務器功能演示一、安裝 HTTPD 服務二、配置個人用戶主頁1. 啟用個人空間功能2. 創建測試用戶及網站目錄3. 配置 SELinux 權限三、配置用戶認證1. 創建密碼文件2. 配置目錄認證3. 重啟服務生效四、配置 SSL 加密網站1. 生成自簽名證書2. 配置 SSL 虛擬主機3. 重啟服務驗證…

把Java程序部署到本地Docker

一&#xff1a;clean && install程序install之后會在target中生成jar包 二&#xff1a;準備三個文件&#xff08;1&#xff09;其中Dockerfile主要起到配置作用&#xff1a;# 基礎鏡像 FROM openjdk:17-jdk-slim # 作者 MAINTAINER "" # 配置 ENV PAR…

Java學習-------外觀模式

在軟件開發中&#xff0c;隨著系統的不斷迭代&#xff0c;模塊會越來越多&#xff0c;模塊之間的依賴關系也會變得錯綜復雜。這不僅會增加開發難度&#xff0c;還會讓系統的維護和擴展變得棘手。而外觀模式就像一位 “前臺接待員”&#xff0c;為復雜的系統提供一個簡潔統一的接…

Go語言-->變量

Go語言–>變量 在 Go 語言中&#xff0c;定義變量有幾種常見的方式。下面是一些常見的語法和用法&#xff1a; 1. 使用 var 關鍵字定義變量 最常見的方式是使用 var 關鍵字&#xff0c;后面跟上變量名和類型。你也可以為變量賦初值。 基本格式&#xff1a; var variableName…

分布式鏈路追蹤的實現原理

分布式鏈路追蹤系統的實現涉及多個核心技術環節&#xff0c;下面我將從數據采集、上下文傳播、存儲分析等維度深入解析其工作原理。 一、核心架構組件 1. 系統組成模塊 #mermaid-svg-pDlZY54w2Z0Bp1H1 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-si…

Python爬蟲實戰:研究micawber庫相關技術構建網頁采集系統

1. 引言 1.1 研究背景與意義 在當今信息爆炸的時代,互聯網上的數據量呈現出爆炸式增長。如何從海量的網頁數據中提取有價值的信息,成為了一個重要的研究課題。網絡爬蟲作為一種自動獲取網頁內容的技術,為解決這一問題提供了有效的手段。通過網絡爬蟲,可以快速、高效地采集…

前端框架Vue3(三)——路由和pinia

路由的理解 路由就是一組key-value的對應關系&#xff0c;多個路由&#xff0c;需要經過路由器的管理。 路由-基本切換效果 導航區、展示區請來路由器制定路由的具體規則&#xff08;什么路徑&#xff0c;對應著什么組件&#xff09;形成一個一個的路由 【兩個注意點】 路由組件…

【go】實現BMI計算小程序與GUI/WEB端實現

好的&#xff0c;下面是用 Go 語言實現的一個簡單的 BMI&#xff08;Body Mass Index&#xff0c;身體質量指數&#xff09;計算器&#xff0c;包含中文注釋與完整代碼&#xff0c;可以直接運行。 一、BMI 計算公式 BMI體重&#xff08;kg&#xff09;身高2&#xff08;m2&…

Windows系統優化命令-記錄

閑著無聊&#xff0c;近來電腦有些卡頓&#xff0c;記錄一下相關命令。最好的命令還是格式化╮(╯▽╰)╭ 1. 磁盤清理相關命令 cleanmgr - 磁盤清理工具 cleanmgr啟動磁盤清理工具&#xff0c;可清理臨時文件、回收站等內容 diskpart - 磁盤分區工具 diskpart用于磁盤管理&…