עדכון מסמכים
חלק מהיחידה מסדי נתונים עם 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 עבור 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);
});
// הוסיפו כאן PATCH /books/:id.
app.listen(3000, () => {
console.log('Bookshelf is running on port 3000');
});
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה מסדי נתונים עם MongoDB
תרגלו בעצמכם: Express אונליין