מסנני שאילתות
חלק מהיחידה מסדי נתונים עם MongoDB במסלול ה-Node.js של Coddy. שיעור 9 מתוך 29.
לקוח רוצה לעיתים קרובות רק ספרים מסוימים, ובסיס הנתונים יכול לבחור אותם.
האובייקט שמעבירים אל find הוא מסנן: מסמך מתאים כאשר כל שדה במסנן מתאים. ערך פשוט פירושו שווה. אופרטור הוא מפתח שמתחיל ב־$ ומשווה במקום זאת: $gte פירושו גדול או שווה, $lte קטן או שווה. שני אופרטורים באותו שדה חולקים אובייקט אחד: { total: { $gte: 20, $lte: 50 } } משאיר את הסכומים שבין 20 ל־50.
// הזמנות ששולמו בסכום של 20 ומעלה
await orders.find({ status: 'paid', total: { $gte: 20 } }).toArray();גם לסוגים יש חשיבות: { $gte: '20' } משווה מחרוזת, ו־MongoDB לעולם לא יתאים מחרוזת לשדה מספרי. כל מה שנמצא ב־req.query הוא מחרוזת, לכן יש להמיר מספרים למספרים באמצעות Number() לפני שמעבירים אותם למסנן.
אתגר
קלבשלב הזה נפתח פרויקט API מוכן של מדף ספרים בקורס, ולא את קובצי הפרויקט שלך מתוך חיפוש לפי ObjectId (כולל server.js). העבודה הקודמת שלך נשארת בשיעור משלה. קרא את הקבצים שסופקו לפני עריכת server.js. העותק הזה כולל נתיבים להוספת ספרים למדף ולחיפוש לפי ObjectId.
לקוחות רוצים רק ספרים מסוימים: ספרים של סופר אחד, או ספרים משנים מסוימות. תן למסד הנתונים לבחור אותם.
- ב־
server.js, שנה אתGET /books. בנה אובייקט מסנן ממחרוזת השאילתה והעבר אותו ל־find. הנתיב עדיין מחזיר מערך JSON של ספרים. ?author=Jane%20Austenמחזיר רק את הספרים שהערך שלauthorשלהם הוא בדיוקJane Austen. (%20הוא האופן שבו כתובת URL כותבת רווח.)?from=1960מחזיר את הספרים ששנתyearשלהם היא 1960 או מאוחרת יותר.?to=1980מחזיר את הספרים משנת 1980 או מוקדמים יותר. כשמשתמשים בשניהם, הספר חייב להיות בטווח שבין שתי השנים, והשנים עצמן נכללות. אפשר להשתמש בכל אחד מהם גם לבדו.- ערכי השאילתה תמיד מגיעים כמחרוזות, אבל השנים המאוחסנות הן מספרים. המר את
fromואתtoלמספרים לפני שהם נכנסים למסנן, אחרת שום דבר לא יתאים. - ללא שאילתה, הנתיב מחזיר את כל הספרים, כמו קודם. נסה זאת: שלח
GET /books?from=1960&to=1980: תקבל את Dune (1965) ואת Kindred (1979). שלחGET /books?from=1970: תקבל רק את Kindred. שלחGET /books?to=1900: תקבל רק את Emma (1815). שלחGET /books?author=Jane%20Austen: תקבל רק את Emma. שלחGET /books: תקבל את שלושתם.
נסו בעצמכם
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 });
}
app.get('/', (req, res) => {
res.send('Bookshelf API');
});
app.get('/books', async (req, res) => {
const list = await books.find().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/:id', async (req, res) => {
if (!ObjectId.isValid(req.params.id)) {
return sendError(res, 400, 'Not a valid id');
}
const book = await books.findOne({ _id: new ObjectId(req.params.id) });
if (!book) {
return sendError(res, 404, 'No such book');
}
res.json(book);
});
app.listen(3000, () => {
console.log('Bookshelf is running on port 3000');
});
כל השיעורים ביחידה מסדי נתונים עם MongoDB
תרגלו בעצמכם: Express אונליין