昨天我們學會了直接用 MongoDB Driver 操作資料,
例如 insertOne
、find
、updateOne
、deleteOne
。
雖然能操作基本的CURD,但在實際開發時會有兩個問題:
因此最佳做法是 透過後端 API 封裝 CRUD 操作,前端只需發送請求。
在 RESTful 設計裡,每個 CRUD 對應到一個 API:
動作 | MongoDB | 典型 API | 狀態碼 |
---|---|---|---|
Create | insertOne |
POST /users |
201 Created |
Read(列表) | find |
GET /users |
200 OK |
Read(單筆) | findOne |
GET /users/:id |
200 / 404 |
Update | updateOne |
PUT /users/:id |
200 / 404 |
Delete | deleteOne |
DELETE /users/:id |
204 / 404 |
這樣設計清楚直觀,也符合業界慣例。
下面是我們的 API 實作,包含了 資料驗證 與 防呆處理。
import express from "express";
import { MongoClient, ObjectId } from "mongodb";
const app = express();
const url = "mongodb://localhost:27017";
const client = new MongoClient(url);
app.use(express.json()); // 解析 JSON body
// 初始化 MongoDB 連線
let users;
async function connectDB() {
await client.connect();
const db = client.db("testdb");
users = db.collection("users");
}
connectDB();
// ➕ Create
app.post("/users", async (req, res) => {
const { name, age } = req.body;
if (!name || typeof name !== "string") {
return res.status(400).json({ error: "姓名必填,且必須是字串" });
}
if (age && typeof age !== "number") {
return res.status(400).json({ error: "年齡必須是數字" });
}
const result = await users.insertOne({ name, age, createdAt: new Date() });
res.status(201).json({ message: "新增成功", id: result.insertedId });
});
// 📖 Read (全部)
app.get("/users", async (req, res) => {
const allUsers = await users.find().toArray();
res.json(allUsers);
});
// 📖 Read (單筆)
app.get("/users/:id", async (req, res) => {
try {
const user = await users.findOne({ _id: new ObjectId(req.params.id) });
if (!user) return res.status(404).json({ error: "找不到該使用者" });
res.json(user);
} catch {
res.status(400).json({ error: "ID 格式不正確" });
}
});
// ✏️ Update
app.put("/users/:id", async (req, res) => {
try {
const { name, age } = req.body;
if (!name && !age) {
return res.status(400).json({ error: "必須提供要更新的欄位" });
}
const result = await users.updateOne(
{ _id: new ObjectId(req.params.id) },
{ $set: { ...(name && { name }), ...(age && { age }) } }
);
if (result.matchedCount === 0) {
return res.status(404).json({ error: "找不到該使用者" });
}
res.json({ message: "更新成功" });
} catch {
res.status(400).json({ error: "ID 格式不正確" });
}
});
// ❌ Delete
app.delete("/users/:id", async (req, res) => {
try {
const result = await users.deleteOne({ _id: new ObjectId(req.params.id) });
if (result.deletedCount === 0) {
return res.status(404).json({ error: "找不到該使用者" });
}
res.json({ message: "刪除成功" });
} catch {
res.status(400).json({ error: "ID 格式不正確" });
}
});
app.listen(3000, () =>
console.log("🚀 API 運行中:http://localhost:3000")
);
使用 cURL 或 Postman 測試:
# 新增 (Create)
curl -X POST http://localhost:3000/users \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "age": 25}'
# 查詢所有 (Read)
curl http://localhost:3000/users
# 查詢單筆 (Read by ID)
curl http://localhost:3000/users/<id>
# 更新 (Update)
curl -X PUT http://localhost:3000/users/<id> \
-H "Content-Type: application/json" \
-d '{"age": 30}'
# 刪除 (Delete)
curl -X DELETE http://localhost:3000/users/<id>
今天我們完成了:
前端可以直接呼叫 API 來操作 MongoDB,而不是直接連線資料庫,這樣的架構更安全、更符合真實專案需求。明天要接續學習新的內容-Mongoose。