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

تدرّب بنفسك: Playground لـ Express