تخطَّ إلى المحتوى

البحث في MongoDB: find والمعاملات

الدرس 4 من 8 · MongoDB

تخيّل أنك أمين المكتبة، والزوار يسألونك: «أريد كتب التقنية»، «ما الكتب التي صفحاتها أكثر من 200؟»، «ما أحدث كتابين؟». في MongoDB، كل سؤال من هذه يتحول إلى استعلام find. وفي هذا الدرس ستتعلم كيف تكتب هذه الاستعلامات، وستلاحظ أن لغة البحث نفسها مستند يصف ما تبحث عنه.

سنعمل على الكتب الخمسة التي أضفناها في الدرس السابق: رحلة إلى القمر (2020)، وأسرار البحار (2018)، والبرمجة للمبتدئين (2023، غير متاح)، وحكايات جدتي (2015)، وعالم الروبوتات (2022).

db.books.find({}, { title: 1, year: 1, _id: 0 })
الناتج
[
{ title: 'رحلة إلى القمر', year: 2020 },
{ title: 'أسرار البحار', year: 2018 },
{ title: 'البرمجة للمبتدئين', year: 2023 },
{ title: 'حكايات جدتي', year: 2015 },
{ title: 'عالم الروبوتات', year: 2022 }
]

find تأخذ معاملين:

  1. الفلتر: أي المستندات تريد. {} الفارغ يعني «كلها».
  2. الإسقاط (Projection): أي الحقول تعرض. 1 يعني «اعرض»، و _id: 0 يعني «أخفِ المعرّف» لأنه يظهر افتراضياً.

بدون الإسقاط تظهر المستندات كاملة بكل حقولها. والإسقاط مثل SELECT title, year في SQL.

db.books.find({ available: false }, { title: 1, _id: 0 })
الناتج
[ { title: 'البرمجة للمبتدئين' } ]

الفلتر { available: false } يعني «حيث available تساوي false». الاستعلام مستند يشبه المستندات التي تبحث عنها.

للمقارنات غير المساواة، تستخدم معاملات تبدأ بعلامة $:

db.books.find({ pages: { $gt: 200 } }, { title: 1, pages: 1, _id: 0 })
الناتج
[
{ title: 'أسرار البحار', pages: 240 },
{ title: 'البرمجة للمبتدئين', pages: 320 },
{ title: 'عالم الروبوتات', pages: 210 }
]
المعامل المعنى
$eq و $ne يساوي، لا يساوي
$gt و $gte أكبر من، أكبر من أو يساوي
$lt و $lte أصغر من، أصغر من أو يساوي
$in و $nin ضمن قائمة، ليس ضمن قائمة

الحروف اختصارات إنجليزية: gt من greater than، و lt من less than، و e في gte من equal.

و (AND): ضع الشروط في نفس المستند، وتُدمج تلقائياً:

db.books.find(
{ price: { $gte: 50, $lte: 120 }, available: true },
{ title: 1, price: 1, _id: 0 }
)
الناتج
[
{ title: 'رحلة إلى القمر', price: 75.5 },
{ title: 'أسرار البحار', price: 90 }
]

السعر بين 50 و 120 و الكتاب متاح. «البرمجة للمبتدئين» سعره 120 لكنه غير متاح، فاستُبعد.

ضمن قائمة: $in

db.books.find({ year: { $in: [2015, 2023] } }, { title: 1, year: 1, _id: 0 })
الناتج
[
{ title: 'البرمجة للمبتدئين', year: 2023 },
{ title: 'حكايات جدتي', year: 2015 }
]

أو (OR): المعامل $or مع مصفوفة شروط:

db.books.find(
{ $or: [ { pages: { $lt: 100 } }, { price: { $gt: 140 } } ] },
{ title: 1, _id: 0 }
)
الناتج
[ { title: 'حكايات جدتي' }, { title: 'عالم الروبوتات' } ]

كتاب قصير (أقل من 100 صفحة) أو غالٍ (أكثر من 140).

هنا تتفوق MongoDB. ابحث عن قيمة داخل مصفوفة كأنها حقل عادي:

db.books.find({ genres: 'تقنية' }, { title: 1, _id: 0 })
الناتج
[ { title: 'البرمجة للمبتدئين' }, { title: 'عالم الروبوتات' } ]

genres مصفوفة، لكن MongoDB تفهم أنك تقصد: «الكتب التي تحتوي مصفوفة تصنيفاتها على “تقنية”». لا JOIN ولا جداول إضافية.

البحث في الحقول المتداخلة

Section titled “البحث في الحقول المتداخلة”

استخدم النقطة للوصول إلى حقل داخل مستند متداخل، مع وضع الاسم بين علامتي تنصيص:

db.books.find({ 'publisher.country': 'الأردن' }, { title: 1, 'publisher.name': 1, _id: 0 })
الناتج
[
{ title: 'أسرار البحار', publisher: { name: 'دار المعرفة' } },
{ title: 'عالم الروبوتات', publisher: { name: 'دار المعرفة' } }
]

الترتيب والتحديد: sort و limit و skip

Section titled “الترتيب والتحديد: sort و limit و skip”
db.books.find({}, { title: 1, price: 1, _id: 0 }).sort({ price: -1 }).limit(2)
الناتج
[
{ title: 'عالم الروبوتات', price: 150 },
{ title: 'البرمجة للمبتدئين', price: 120 }
]
  • sort({ price: -1 }): رتّب بالسعر تنازلياً، و 1 للتصاعدي.
  • limit(2): خذ أول نتيجتين فقط.
  • skip(n): تخطَّ أول n نتائج، ومع limit تصنع صفحات النتائج.
db.books.findOne({ author: 'منى علي' }, { title: 1, _id: 0 })
الناتج
{ title: 'البرمجة للمبتدئين' }

findOne تُرجع أول مستند مطابق كمستند مباشر (لا كمصفوفة)، أو null إذا لم تجد شيئاً. و db.books.countDocuments({ available: true }) تعدّ المطابقين، والناتج هنا 4.

على مجموعة الكتب:

  1. اعرض عناوين الكتب المنشورة بعد 2019 فقط.
  2. اعرض الكتب المتاحة التي سعرها أقل من 100.
  3. اعرض كتب تصنيف «مغامرات».
  4. اعرض الكتب الصادرة عن ناشرين من مصر.
  5. اعرض أقدم كتابين بالعنوان والسنة فقط.
  6. تحدٍّ: اعرض الكتب التي تصنيفها «علوم» أو عدد صفحاتها أقل من 100.
  • نسيان علامتي التنصيص مع النقطة: { publisher.country: '...' } خطأ في الصياغة. الصحيح { 'publisher.country': '...' }.
  • نسيان $ في المعاملات: { pages: { gt: 200 } } تبحث عن مستند حقل pages فيه يساوي { gt: 200 } حرفياً، فلا تجد شيئاً بصمت.
  • خلط الإسقاط: لا تخلط 1 و 0 في نفس الإسقاط، إلا مع _id: 0.

سؤال

أي فلتر يجد الكتب التي صفحاتها أقل من 150؟

سؤال

الحقل tags مصفوفة. ماذا يجد الاستعلام find({ tags: 'جديد' })؟

  • find(فلتر, إسقاط): الفلتر يحدد المستندات، والإسقاط يحدد الحقول.
  • المعاملات $gt و $lt و $gte و $lte و $in و $ne للمقارنات.
  • الشروط في نفس المستند تعني AND، و $or لـ OR.
  • البحث في المصفوفات مباشر، والحقول المتداخلة بالنقطة بين علامتي تنصيص.
  • sort و limit و skip للترتيب والصفحات، و findOne و countDocuments للمستند الواحد والعدد.