Menu
CoddyTech

מסנני שאילתות

חלק מהיחידה מסדי נתונים עם 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() לפני שמעבירים אותם למסנן.

challenge icon

אתגר

קל

בשלב הזה נפתח פרויקט API מוכן של מדף ספרים בקורס, ולא את קובצי הפרויקט שלך מתוך חיפוש לפי ObjectId (כולל server.js). העבודה הקודמת שלך נשארת בשיעור משלה. קרא את הקבצים שסופקו לפני עריכת server.js. העותק הזה כולל נתיבים להוספת ספרים למדף ולחיפוש לפי ObjectId.

לקוחות רוצים רק ספרים מסוימים: ספרים של סופר אחד, או ספרים משנים מסוימות. תן למסד הנתונים לבחור אותם.

  1. ב־server.js, שנה את GET /books. בנה אובייקט מסנן ממחרוזת השאילתה והעבר אותו ל־find. הנתיב עדיין מחזיר מערך JSON של ספרים.
  2. ?author=Jane%20Austen מחזיר רק את הספרים שהערך של author שלהם הוא בדיוק Jane Austen. (%20 הוא האופן שבו כתובת URL כותבת רווח.)
  3. ?from=1960 מחזיר את הספרים ששנת year שלהם היא 1960 או מאוחרת יותר. ?to=1980 מחזיר את הספרים משנת 1980 או מוקדמים יותר. כשמשתמשים בשניהם, הספר חייב להיות בטווח שבין שתי השנים, והשנים עצמן נכללות. אפשר להשתמש בכל אחד מהם גם לבדו.
  4. ערכי השאילתה תמיד מגיעים כמחרוזות, אבל השנים המאוחסנות הן מספרים. המר את from ואת to למספרים לפני שהם נכנסים למסנן, אחרת שום דבר לא יתאים.
  5. ללא שאילתה, הנתיב מחזיר את כל הספרים, כמו קודם. נסה זאת: שלח 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 אונליין