NahdaAIنهضة
NoSQL Databases • المستوى الثاني • الدرس 4

التصفية المتقدمة داخل المصفوفات ($elemMatch)

العودة لفهرس المستوى

أهداف الدرس

  • استخدام $elemMatch للبحث بشرطين معاً على نفس الكائن بداخل المصفوفة.
  • تجنب أخطاء الفلترة العامة على المصفوفات المضمنة.
  • دمج $elemMatch مع معاملات المقارنة ($gt، $gte، $lt).
  • تطبيق $elemMatch في أنظمة الطلبات والتجارة الإلكترونية.

1. المشكلة بدون $elemMatch

تخيّل أن لديك مصفوفة items بداخل مستند الطلب، كل عنصر يمثل منتجاً:

javascript
{
  orderNumber: "ORD-002",
  customer: "أحمد علي",
  items: [
    { product_id: 101, name: "لابتوب", quantity: 5, price: 1500 },
    { product_id: 103, name: "كيبورد", quantity: 2, price: 200 }
  ]
}
الاستعلام الخاطئ الشائع
db.orders.find({
  "items.product_id": 101,
  "items.quantity": { $gt: 4 }
});

هذا الاستعلام يبحث عن أي طلب يحتوي على:
- product_id: 101 في أي عنصر، و
- quantity > 4 في أي عنصر (ربما مختلف!)
النتيجة: قد يُطابق طلباً ليس فيه لابتوب بكمية كبيرة أصلاً!

2. الحل — $elemMatch

$elemMatch يضمن أن جميع الشروط تتحقق على نفس العنصر داخل المصفوفة:

javascript
db.orders.find({
  items: {
    $elemMatch: {
      product_id: 101,
      quantity: { $gt: 4 }
    }
  }
});

// النتيجة: فقط الطلبات التي فيها
// "لابتوب بكمية > 4" في نفس عنصر المصفوفة
بدون $elemMatch

الشروط تُطبَّق على عناصر مختلفة — نتائج غير دقيقة.

مع $elemMatch

كل الشروط تُطبَّق على نفس العنصر — نتائج دقيقة.

3. دمج $elemMatch مع معاملات المقارنة

$gt — أكبر من
quantity: { $gt: 5 }
$gte — أكبر أو يساوي
quantity: { $gte: 5 }
$lt — أصغر من
quantity: { $lt: 3 }
شرطان على نفس الحقل
quantity: { $gt: 2, $lt: 6 }

4. استخدامات واقعية

1.التجارة الإلكترونية: الطلبات التي فيها منتج معيّن بكمية محددة.
2.أنظمة التوظيف: المرشحون بمهارة معيّنة ومستوى خبرة محدد.
3.التعليم: الطلاب الذين حصلوا على درجة محددة في مادة معيّنة.
التطبيق العملي المباشر

تحدي الدرس الرابع: $elemMatch متقدم

قم بالتعديل على الكود بداخل المحرر أدناه لتطبيق المتطلبات التالية:

  1. غيّر شرط الكمية من $gt: 2 إلى $gt: 5.
  2. أضف استعلاماً جديداً للبحث عن product_id: 102 بـ $gte: 5.
  3. أضف استعلاماً مع Projection لعرض orderNumber و customer فقط.
  4. اعرض جميع الطلبات بـ db.orders.find({}).
  5. اطبع عدد الطلبات الإجمالي بـ countDocuments().
⏳ جارٍ تحميل المحرر التفاعلي...