تحديث المستندات
جزء من قسم قواعد البيانات باستخدام MongoDB في رحلة Node.js على Coddy. الدرس 14 من 29.
يجب أن يؤدي تصحيح سنة كتاب إلى تغيير هذا الحقل وحده وترك الحقول الأخرى كما هي.
تغيّر updateOne(filter, update) المستند الأول الذي يطابقه عامل التصفية. يتكوّن التحديث من عوامل: يكتب $set الحقول التي تحددها ويُبقي كل الحقول الأخرى. يُرفض الكائن العادي الذي لا يحتوي على أي عامل مع الرسالة "Update document requires atomic operators".
const result = await players.updateOne(
{ name: 'Ada' },
{ $set: { score: 120, level: 4 } }
);
result.matchedCount; // 1 إذا تطابق أحد اللاعبين، و0 إذا لم يتطابق أي لاعب
result.modifiedCount; // 0 عندما تكون القيم متطابقة بالفعلميّز المستند غير الموجود عن المستند الذي لم يتغير باستخدام matchedCount، لا modifiedCount. لا يعيد التحديث المستند، لذا اقرأه مرة أخرى باستخدام findOne.
التحدي
سهليريد أحد العملاء تصحيح حقل واحد في كتاب، مثل سنة خاطئة، من دون إرسال الكتاب كله مرة أخرى.
- في
server.js، أسفل التعليق// Add PATCH /books/:id here.، أضف مسارًا لـPATCH /books/:id. - ابدأه بالطريقة نفسها التي يبدأ بها الآن
GET /books/:id: استدعِparseId(req, res). عندما يكون المعرّف غير صالح، يكونparseIdقد أرسل بالفعل استجابة بالرمز 400 ويعيدnull، لذا توقّف عند هذا الحد. - غيّر الحقول التي يرسلها نص الطلب فقط، واترك كل حقل آخر كما هو. يغيّر نص الطلب
{ "year": 1966 }السنة ولا يغيّر أي شيء آخر. - عندما لا يوجد كتاب بهذا
_id، أرسل استجابة بحالة 404 وخطأ، مثل{ "error": "No such book" }. - وإلا، أرسل استجابة بحالة 200 والكتاب كاملًا كما هو مخزّن الآن:جرّب ذلك: أرسل
{ "_id": "6720a1f4c2b9e81d3a5f0c11", "title": "Dune", "author": "Frank Herbert", "year": 1966, "isbn": "9780441013593", "genre": "scifi" }GET /booksوانسخ_idالخاص بـ Dune. انسخه مجددًا بعد كل ضغطة على «العب»، لأن كل ضغطة تمنح معرّفات جديدة. أرسلPATCH /books/متبوعًا بـ_idالخاص بـ Dune، مع نص الطلب{ "year": 1966 }. ستحصل على استجابة 200 وكتاب Dune مع"year": 1966، مع بقاء كل الحقول الأخرى دون تغيير، وتُظهر علامة التبويب Data النتيجة نفسها. أرسل الطلب نفسه مرة أخرى: ستظل تحصل على استجابة 200، لأن الكتاب موجود حتى وإن لم يتغير شيء هذه المرة. أرسلPATCH /books/000000000000000000000000مع{ "year": 1966 }: ستحصل على استجابة 404. أرسلPATCH /books/42: ستحصل على استجابة 400.
جرّب بنفسك
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 إذا كان المعرّف غير صالح.
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);
});
// أضف PATCH /books/:id هنا.
app.listen(3000, () => {
console.log('Bookshelf is running on port 3000');
});
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس قواعد البيانات باستخدام MongoDB
تدرّب بنفسك: Playground لـ Express