حذف المستندات
جزء من قسم قواعد البيانات باستخدام MongoDB في رحلة Node.js على Coddy. الدرس 16 من 29.
تتطلب إزالة كتاب استدعاءً واحدًا، لكن لا يزال على الخادم إخبار العميل عمّا إذا كان هناك كتاب لإزالته.
تزيل deleteOne(filter) أول مستند مطابق، وتُرجع { deletedCount }: القيمة 1 عند إزالة مستند، و0 عندما لا يطابق أي مستند. تُرجع عملية الحذف الناجحة 204 No Content، وهي حالة لا تحتوي على متن، وتُرسل باستخدام res.status(204).end().
const result = await sessions.deleteOne({ token });
if (result.deletedCount === 0) {
// لم تكن هناك أي جلسة تحمل ذلك الرمز
}يجب ألا تنجح إزالة المعرّف نفسه مرتين. في المرة الثانية لن يتبقى شيء، وينبغي أن يتلقى العميل استجابة 404.
التحدي
سهليمكن للعملاء حذف كتاب، ويحتاجون إلى معرفة ما إذا كان هناك كتاب لحذفه.
- في
server.js، أضف مسارDELETE /books/:id. استخدمparseIdللتعامل مع المعرّف غير الصالح، وستكون الاستجابة عندها 400. - عندما يحذف المسار كتابًا، أرسل استجابة بالحالة 204 ومن دون أي محتوى على الإطلاق. أنهِ الاستجابة من دون إرسال JSON.
- عندما لا يوجد كتاب يحمل
_idهذا، أرسل استجابة بالحالة 404 وخطأ، مثل{ "error": "No such book" }. لذا فإن حذف الكتاب نفسه مرة ثانية يعطي أيضًا استجابة 404، لأنه حُذف بالفعل. جرّب ذلك: أرسلGET /booksوانسخ_idالخاص بـ Emma. أرسلDELETE /books/<Emma's _id>: ستحصل على 204 ومحتوى فارغ. أرسل الطلب نفسه مرة أخرى: ستحصل على 404. أرسلGET /books/<Emma's _id>: ستحصل أيضًا على 404. أرسلGET /books: ستحصل على Dune وKindred فقط، وستعرض علامة تبويب Data كتابين. اضغط على «العب» لاستعادة Emma.
جرّب بنفسك
import express from 'express';
import { MongoClient, ObjectId } from 'mongodb';
const client = new MongoClient('mongodb://localhost:27017');
const db = client.db('shelf');
const books = db.collection('books');
await books.insertMany([
{ title: 'Dune', author: 'Frank Herbert', year: 1965, isbn: '9780441013593', genre: 'scifi' },
{ title: 'Kindred', author: 'Octavia E. Butler', year: 1979, isbn: '9780807083697', genre: 'scifi' },
{ title: 'Emma', author: 'Jane Austen', year: 1815, isbn: '9780141439587', genre: 'classic' },
]);
const app = express();
app.use(express.json());
// تُرجع كل حالة خطأ { error: message }.
function sendError(res, status, message) {
res.status(status).json({ error: message });
}
// يُرجع :id بوصفه ObjectId، أو null بعد إرسال استجابة 400 إذا كان id غير صالح.
function parseId(req, res) {
if (ObjectId.isValid(req.params.id)) {
return new ObjectId(req.params.id);
}
sendError(res, 400, 'Not a valid id');
return null;
}
app.get('/', (req, res) => {
res.send('Bookshelf API');
});
app.get('/books', async (req, res) => {
const filter = {};
if (req.query.author) {
filter.author = req.query.author;
}
if (req.query.from || req.query.to) {
filter.year = {};
if (req.query.from) {
filter.year.$gte = Number(req.query.from);
}
if (req.query.to) {
filter.year.$lte = Number(req.query.to);
}
}
const list = await books.find(filter).toArray();
res.json(list);
});
app.post('/books', async (req, res) => {
const book = req.body;
await books.insertOne(book);
res.status(201).json(book);
});
app.get('/books/newest', async (req, res) => {
const n = Number(req.query.n) || 3;
const list = await books
.find({}, { projection: { title: 1, year: 1, _id: 0 } })
.sort({ year: -1 })
.limit(n)
.toArray();
res.json(list);
});
app.get('/books/:id', async (req, res) => {
const id = parseId(req, res);
if (!id) return;
const book = await books.findOne({ _id: id });
if (!book) {
return sendError(res, 404, 'No such book');
}
res.json(book);
});
app.patch('/books/:id', async (req, res) => {
const id = parseId(req, res);
if (!id) return;
const result = await books.updateOne({ _id: id }, { $set: req.body });
if (result.matchedCount === 0) {
return sendError(res, 404, 'No such book');
}
res.json(await books.findOne({ _id: id }));
});
app.post('/books/:id/copies', async (req, res) => {
const id = parseId(req, res);
if (!id) return;
const result = await books.updateOne({ _id: id }, { $inc: { copies: 1 } });
if (result.matchedCount === 0) {
return sendError(res, 404, 'No such book');
}
res.json(await books.findOne({ _id: id }));
});
app.post('/books/:id/tags', async (req, res) => {
const id = parseId(req, res);
if (!id) return;
const result = await books.updateOne({ _id: id }, { $push: { tags: req.body.tag } });
if (result.matchedCount === 0) {
return sendError(res, 404, 'No such book');
}
res.json(await books.findOne({ _id: id }));
});
app.listen(3000, () => {
console.log('Bookshelf is running on port 3000');
});
جميع دروس قواعد البيانات باستخدام MongoDB
تدرّب بنفسك: Playground لـ Express