عوامل تصفية الاستعلام
جزء من قسم قواعد البيانات باستخدام 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
تدرّب بنفسك: Playground لـ Express