MongoDB: استعلامات المصفوفات والوثائق المتداخلة

آخر تحديث: 2026-08-26

تعد المستندات والمصفوفات المتداخلة من الميزات الأساسية في MongoDB — لذا عليك إتقانها للاستفادة القصوى من نموذج المستندات.

تقدم هذه الدورة نظرة متعمقة على استعلامات المصفوفات، وترميز نقاط المستندات المتداخلة، والمطابقة التامة باستخدام $elemMatch، وعمليات تحديث المصفوفات.

1. ما ستتعلمه



2. القصة الحقيقية لمهندس بيانات في مجال التجارة الإلكترونية

(1) المشكلة: الاستعلامات على المستندات المتداخلة تُرجع نتائج غير صحيحة

كانت أليس تعمل على صيانة نظام مراجعة المنتجات عندما واجهت خطأً في الاستعلام:

JAVASCRIPT
// ❌ Counterexample:Search"Rating >= 4 and includes 'good' Keywords"Comments on
db.products.find({
  "reviews.rating": { $gte: 4 },
  "reviews.content": /good/i
});
// ⚠️ Question:May match different comments(One comment, high rating,Another one containing good)
// Expectations:A comment meets both conditions at the same time

(2) حل للمطابقة التامة باستخدام $elemMatch

JAVASCRIPT
// ✅ Correct Example:Use $elemMatch
db.products.find({
  reviews: {
    $elemMatch: {
      rating: { $gte: 4 },
      content: /good/i
    }
  }
});
// ✅ Correct:A single comment that meets all of the following criteria

100%
graph TB
    subgraph "Embedded Documentation"
        A1[products Gathering] --> A2[Document 1<br/>address: {<br/>  city: Tokyo<br/>  country: Japan<br/>}]
    end

    subgraph "Citation-Style Documentation"
        B1[products Gathering] --> B2[Document 1<br/>addressId: ObjectId]
        B3[addresses Gathering] --> B4[Document 1<br/>city: Tokyo]
        B2 -.->|Search| B3
    end

    style A2 fill:#d4edda

3. ترميز عقد المستندات المتداخلة

شرح المفهوم: يُقصد بالمستند المُضمَّن المستند الذي يحتوي على مستند آخر كقيمة لحقل ما. تدعم MongoDB ما يصل إلى 100 مستوى من التداخل؛ ومع ذلك، يُنصح في بيئات الإنتاج بعدم تجاوز 3 مستويات. الترميز بالنقطة هو طريقة للوصول إلى الحقول المتداخلة باستخدام صيغة "field.subfield.subsubfield"، وهو الآلية الأساسية للاستعلام عن البيانات المتداخلة وتحديثها في MongoDB.

كيفية العمل: عندما يقوم MongoDB بتحليل الترميز النقطي، فإنه يحدد مسارات الحقول طبقةً تلو الأخرى من المستويات الخارجية إلى الداخلية. يقوم محرك الاستعلام بتقسيم "specs.screen.size" إلى doc.specs.screen.size ويتنقل عبر شجرة مستند BSON مستوىً تلو الآخر. كما تدعم الفهارس الحقول المكتوبة بالترميز النقطي؛ على سبيل المثال، يمكن استخدام { "specs.screen.size": 1 } لإنشاء فهارس فعالة.

100%
graph TD
    A[BSON Document] --> B[specs: Object]
    B --> C[screen: Object]
    C --> D["size: '6.5'"]
    C --> E["type: 'OLED'"]
    B --> F[battery: Object]
    F --> G["capacity: '4500mAh'"]
    
    H["specs.screen.size"] -->|Analysis of Dot Notation| D
    I["specs.battery.capacity"] -->|Analysis of Dot Notation| G
    
    style D fill:#d4edda
    style G fill:#d4edda
البعد الوصف
السيناريوهات التي ينطبق عليها البيانات ذات التسلسل الهرمي الثابت التي تُقرأ وتُكتب معًا (مثل العناوين والمواصفات)
الحالات التي لا ينطبق عليها ذلك البيانات ذات التسلسل الهرمي غير المؤكد أو التي يتم تحديثها بشكل متكرر وبشكل مستقل (استخدم المراجع)
التأثير على الأداء مستوى واحد ≈ حقل عادي؛ المستويات المتعددة تتطلب عملية اجتياز — يُوصى بألا يتجاوز عدد المستويات 3 مستويات
دعم الفهرس مدعوم بالكامل؛ { "a.b.c": 1 } يعادل الفهرس العادي

(1) الاستعلام عن المستندات المتداخلة وتحديثها

JAVASCRIPT
// === Nested Document Structure ===
db.products.insertOne({
  sku: 'PHONE-001',
  title: 'Smartphone X',
  specs: {
    screen: { size: '6.5', type: 'OLED' },
    battery: { capacity: '4500mAh', type: 'Li-Po' }
  }
});

// === Dot Notation Query ===
db.products.find({ "specs.screen.size": '6.5' });

// === Multi-level nesting ===
db.products.find({ "specs.battery.capacity": '4500mAh' });

// === Updating Nested Fields ===
db.products.updateOne(
  { sku: 'PHONE-001' },
  { $set: { "specs.battery.capacity": "5000mAh" } }
);


4. استعلامات حقول المصفوفات

شرح المفهوم: تعد المصفوفات من أكثر هياكل البيانات مرونة في نموذج المستندات في MongoDB. يمكن لحقل واحد تخزين قيم متعددة، وتتبع استعلامات MongoDB على حقول المصفوفات مبدأ «التطابق الجزئي» — فما دام عنصر واحد في المصفوفة يستوفي الشرط، يتم اختيار المستند. وهذا يجعل استعلامات المصفوفات قوية في الوقت نفسه عرضة لنتائج غير متوقعة.

كيفية العمل: يستخدم محرك الاستعلام في MongoDB استراتيجية «المطابقة بالتوسيع الضمني» لحقول المصفوفات. عند إجراء استعلام عن { tags: '5g' }، يتحقق المحرك من عناصر المصفوفة واحدة تلو الأخرى؛ فإذا كان أي عنصر يساوي '5g'، يُعتبر ذلك مطابقة. بالنسبة للاستعلامات متعددة الشروط (مثل {"reviews.rating": {$gte:4}, "reviews.content": /good/})، تتطابق كل شرط مع عناصر المصفوفة بشكل مستقل، مما قد يؤدي إلى تطابق عناصر مختلفة — وهذا هو سبب وجود $elemMatch.

100%
graph LR
    A[Query Criteria] --> B{Array Matching Strategies}
    B -->|Single condition| C[Any element matches<br/>tags: '5g']
    B -->|Multi-condition point notation| D[Independent matching of each condition<br/>May hit different elements]
    B -->|Multiple conditions $elemMatch| E[The same element must<br/>Meets all conditions at the same time]
    
    C --> F[✅ Simple and Efficient]
    D --> G[⚠️ May not be accurate]
    E --> H[✅ Exact Match]
    
    style F fill:#d4edda
    style G fill:#fff3cd
    style H fill:#d4edda
طريقة البحث قواعد المطابقة السيناريوهات القابلة للتطبيق
{ tags: '5g' } أي عنصر يساوي «5g» مطابقة لقيمة واحدة
{ tags: { $all: ['5g','amoled'] } } يجب تضمين جميع القيم قيم متعددة
{ tags: { $in: ['5g','fast'] } } يحتوي على أي قيمة قيم متعددة أو مطابقات
{ "tags.0": '5g' } تحديد موضع الفهرس مطابقة الموضع
{ tags: { $size: 3 } } المطابقة التامة لطول المصفوفة مرشح الطول

(1) مطابقة عنصر واحد

JAVASCRIPT
// === An array contains the specified elements ===
db.products.find({ tags: '5g' });
// tags The array contains '5g' All Products

// === The array contains all the specified elements($all)===
db.products.find({ tags: { $all: ['5g', 'amoled'] } });
// Must include both '5g' and 'amoled'

// === The array contains any element($in)===
db.products.find({ tags: { $in: ['5g', 'fast-charging'] } });
// Includes '5g' or 'fast-charging'

(2) الاستعلام عن عناصر المصفوفة باستخدام الرقم الترتيبي

JAVASCRIPT
// === Get the first element of an array ===
db.products.find({ "tags.0": '5g' });
// tags[0] = '5g'

// === Retrieve the second element of the array ===
db.products.find({ "tags.1": 'amoled' });
// tags[1] = 'amoled'

// === Querying the Range of Array Elements ===
db.products.find({ "tags.0": { $in: ['new', 'sale'] } });

(3) التحقق من طول المصفوفة

JAVASCRIPT
// === Exact Match for Array Length ===
db.products.find({ tags: { $size: 3 } });
// Number of tags = 3

// === Query on Array Length Range ===
db.products.find({
  $expr: { $gt: [{ $size: '$tags' }, 3] }
});
// Number of tags > 3


5. $elemMatch: المطابقة التامة

شرح المفهوم: $elemMatch هو عامل مطابقة تامة مصمم خصيصًا لحقول المصفوفات في MongoDB. وهو يضمن أن نفس عنصر المصفوفة يستوفي جميع شروط الاستعلام في آن واحد، بدلاً من أن يستوفي كل عنصر من العناصر المختلفة بعض الشروط فقط. وعندما تكون عناصر المصفوفة كائنات (مثل التعليقات أو الدرجات) ويكون الاستعلام الذي يتطلب ربطًا متعدد الحقول ضروريًا، فإن $elemMatch هو الخيار الصحيح الوحيد.

كيفية العمل: $elemMatch يطبق جميع الشروط على كل عنصر في المصفوفة واحدًا تلو الآخر. ولا يُعتبر العنصر مطابقًا إلا إذا اجتاز جميع اختبارات الشروط في آن واحد. الفرق الرئيسي عن الترميز بالنقطة: في الترميز بالنقطة، تقوم الشروط المتعددة بمسح المصفوفة وقد تتطابق مع عناصر مختلفة؛ أما $elemMatch فيتطلب أن يجتاز عنصر واحد جميع الاختبارات.

100%
sequenceDiagram
    participant Query as Search Engine
    participant Doc as Document<br/>reviews: [{rating:5,content:"bad"},<br/>{rating:3,content:"good"}]
    
    Note over Query,Doc: Dot Notation Query: reviews.rating>=4 AND reviews.content=/good/
    Query->>Doc: Conditions1: rating>=4 → Hit Element0
    Query->>Doc: Conditions2: /good/ → Hit Element1
    Doc-->>Query: ⚠️ Different elements each meet some of the conditions → Return to this document
    
    Note over Query,Doc: $elemMatch Search
    Query->>Doc: Element0: rating>=4 ✅, /good/ ❌ → Mismatch
    Query->>Doc: Element1: rating>=4 ❌ → Mismatch
    Doc-->>Query: ✅ No elements satisfy all of the following conditions → Does not return
بُعد المقارنة تدوين النقاط $elemMatch
دقة المطابقة تتم مطابقة كل شرط على حدة يجب استيفاء جميع الشروط الخاصة بالعنصر نفسه
الصيغة { "a.b": x, "a.c": y } { a: { $elemMatch: { b: x, c: y } } }
الدقة ⚠️ قد تستهدف عناصر مختلفة ✅ دقيقة حتى مستوى العنصر الواحد
الأداء أسرع قليلاً (يمكن استخدام الفهارس بشكل منفصل) أبطأ قليلاً (يتطلب فحص كل عنصر)
دعم الفهارس يمكن معالجة شروط متعددة بشكل منفصل عبر الفهارس يلزم وجود فهرس مركب

(1) القضية الأساسية

JAVASCRIPT
// === Counterexample:Matching Elements in Different Arrays ===
db.products.find({
  "reviews.rating": { $gte: 4 },
  "reviews.content": /good/i
});
// Possible matches:review1.rating=5, review2.content="good"
// That is, different comments each satisfy the condition

// ✅ Correct Example:$elemMatch Match the same element
db.products.find({
  reviews: {
    $elemMatch: {
      rating: { $gte: 4 },
      content: /good/i
    }
  }
});
// A single comment must meet all of the following criteria at the same time

(2) الحالات المعقدة

JAVASCRIPT
// === Multiple conditions elemMatch ===
db.products.find({
  reviews: {
    $elemMatch: {
      rating: { $gte: 4 },
      helpful: { $gt: 10 },
      createdAt: { $gte: new Date('2026-01-01') }
    }
  }
});

// === Nested elemMatch ===
db.students.find({
  courses: {
    $elemMatch: {
      name: 'Math',
      score: { $gte: 90 },
      assignments: {
        $elemMatch: {
          submitted: true,
          grade: { $gte: 80 }
        }
      }
    }
  }
});


6. مُعدِّلات تحديث المصفوفات

شرح المفهوم: توفر MongoDB مجموعة من مُعدِّلات التحديث المخصصة خصيصًا لمعالجة حقول المصفوفات: $push (إلحاق)، $pull (حذف)، $addToSet (إلحاق دون تكرار)، $pop (إزالة العنصر الأول والأخير). عند استخدامها بالاقتران مع العنصر النائب للموضع $ وarrayFilters، تتيح لك هذه العوامل تحديث عناصر محددة في المصفوفة بدقة دون استبدال المصفوفة بأكملها.

كيفية العمل: يتم تنفيذ مُعدِّلات تحديث المصفوفات بشكل متكامل على خادم MongoDB. $push يُضيف عنصرًا إلى نهاية المصفوفة؛ $addToSet يتحقق من وجود العنصر بالفعل قبل إضافته؛ $pull يُضيف عنصرًا إلى نهاية المصفوفة؛ $addToSet يتحقق من وجود العنصر قبل إضافته؛ $pull يحذف عنصرًا بناءً على شرط معين؛ $ يشير العنصر النائب إلى موضع أول عنصر في المصفوفة يطابق شرط الاستعلام؛ $[] يشير إلى جميع العناصر؛ $[filter] يعمل بالاقتران مع arrayFilters لإجراء التحديثات الشرطية.

100%
graph TB
    A[Array Update Modifiers] --> B[$push<br/>Additional Elements]
    A --> C[$pull<br/>Conditional Deletion]
    A --> D[$addToSet<br/>Remove Duplicates and Append]
    A --> E[$pop<br/>Remove the first and last characters]
    
    F[Position Operators] --> G[$<br/>Update the first match]
    F --> H[$[]<br/>Update All Elements]
    F --> I[$[filter]<br/>Conditional Batch Update<br/>In conjunction witharrayFilters]
    
    style B fill:#d4edda
    style C fill:#f8d7da
    style D fill:#cce5ff
    style I fill:#fff3cd
المُعدِّل الوظيفة مثال
$push إضافة عنصر (قابل للتكرار) { $push: { tags: 'new' } }
$each استخدم $push لإضافة عدة عناصر { $push: { tags: { $each: ['a','b'] } } }
$addToSet إزالة التكرارات والإضافة { $addToSet: { tags: 'new' } }
$pull الحذف حسب المعايير { $pull: { tags: 'old' } }
$pop حذف الأول/الأخير { $pop: { tags: 1 } } (حذف الأخير)
$ تحديث العنصر الأول المطابق { $set: { "reviews.$.flagged": true } }
$[] تحديث جميع العناصر { $set: { "reviews.$[].status": "ok" } }
$[f] التحديث الدفعي المشروط { arrayFilters: [{ "f.rating": {$lt:2} }] }

(1) $push: إضافة عنصر

JAVASCRIPT
// === Add a single item ===
db.products.updateOne(
  { sku: 'PHONE-001' },
  { $push: { tags: 'bestseller' } }
);

// === Add multiple($each)===
db.products.updateOne(
  { sku: 'PHONE-001' },
  { $push: { tags: { $each: ['5g', 'amoled', 'fast-charging'] } } }
);

(2) $pull: يحذف عنصرًا

JAVASCRIPT
// === Delete a Specified Value ===
db.products.updateOne(
  { sku: 'PHONE-001' },
  { $pull: { tags: 'old-tag' } }
);

// === Delete Multiple ===
db.products.updateOne(
  { sku: 'PHONE-001' },
  { $pull: { tags: { $in: ['outdated1', 'outdated2'] } } }
);

// === Delete elements that meet the criteria ===
db.products.updateOne(
  { sku: 'PHONE-001' },
  { $pull: { reviews: { rating: { $lt: 2 } } } }
);
// Delete Rating < 2 Comments on

(3) $ العنصر النائب للموضع

JAVASCRIPT
// === Update the first matching array element ===
db.products.updateOne(
  { sku: 'PHONE-001', "reviews.userId": 'user_001' },
  { $set: { "reviews.$.helpful": 10 } }
);
// Update user_001 Comments on

// === Update all matching array elements ===
db.products.updateOne(
  { sku: 'PHONE-001' },
  { $set: { "reviews.$[].status": "approved" } }
);

// === Conditional Update(arrayFilters)===
db.products.updateOne(
  { sku: 'PHONE-001' },
  { $set: { "reviews.$[lowRating].flagged": true } },
  { arrayFilters: [{ "lowRating.rating": { $lt: 2 } }] }
);


7. الفهرس متعدد المفاتيح: فهرسة المصفوفات

شرح المفهوم: عندما يكون حقل الفهرس عبارة عن مصفوفة، يقوم MongoDB تلقائيًا بإنشاء فهرس متعدد المفاتيح. وتتمثل الميزة الرئيسية لهذا الفهرس في أن كل عنصر في المصفوفة يُنشئ مفتاح فهرس منفصل. على سبيل المثال، سيؤدي tags: ['5g', 'amoled'] إلى إنشاء مدخلين في الفهرس، يشير كل منهما إلى نفس المستند. وهذا يضمن أن يكون أداء الاستعلامات الخاصة بحقول المصفوفات مكافئًا لأداء الاستعلامات الخاصة بفهارس الحقول العادية.

كيفية العمل: عند إدراج مستند، يتحقق MongoDB مما إذا كان الحقل المفهرس عبارة عن مصفوفة. إذا كان الأمر كذلك، فإنه ينشئ إدخالاً في الفهرس لكل عنصر. وأثناء إجراء الاستعلام، يستخدم MongoDB الفهارس متعددة المفاتيح لتحديد موقع المستند الذي يحتوي على العنصر المستهدف بسرعة. القيد: يمكن أن يحتوي الفهرس المركب على حقل مصفوفة واحد على الأكثر؛ وإلا فإن عدد إدخالات الفهرس سيزداد بشكل هائل (الضرب الديكارتي).

100%
graph LR
    A[Document<br/>tags: 5g, amoled, fast] --> B[multikey index]
    B --> C["Index Entries: '5g' → docId"]
    B --> D["Index Entries: 'amoled' → docId"]
    B --> E["Index Entries: 'fast' → docId"]
    
    F["Search {tags: '5g'}"] -->|Index Lookup| C
    C --> G[✅ Document in Chinese]
    
    style B fill:#d4edda
    style G fill:#d4edda
قيود المفاتيح المتعددة الوصف
كل عنصر في المصفوفة له مؤشر يؤثر طول المصفوفة على حجم المؤشر
يمكن أن تحتوي الفهارس المركبة على حقل صفيف واحد على الأكثر منع تضخم الفهرس
أداء عالٍ في استعلامات فهرس المصفوفات تعادل الفهارس العادية للحقول
يتعذر فهرسة المصفوفة بأكملها قم بفهرسة العناصر فقط، وليس المصفوفة نفسها

▶ المثال 1: دليل عملي للاستعلام عن المستندات المتداخلة

JAVASCRIPT
// Scene:ShopHub Checking Product Specifications on E-commerce Platforms
db.products.insertOne({
  sku: 'PHONE-002',
  title: 'Smartphone Y',
  specs: {
    screen: { size: '6.7', type: 'AMOLED', refreshRate: '120Hz' },
    battery: { capacity: '5000mAh', type: 'Li-Po', fastCharging: true },
    storage: { ram: '12GB', internal: '256GB' }
  }
});

// Search:AMOLED Products on the Screen
db.products.find({ "specs.screen.type": 'AMOLED' });

// Search:Supports fast charging and has a battery ≥ 5000mAh Products
db.products.find({
  "specs.battery.fastCharging": true,
  "specs.battery.capacity": { $in: ['5000mAh', '6000mAh'] }
});

// Update:Add Screen Protector Information
db.products.updateOne(
  { sku: 'PHONE-002' },
  { $set: { "specs.screen.protection": "Gorilla Glass 5" } }
);

الإخراج:

TEXT 📖 للعرض فقط
{ acknowledged: true, insertedId: ObjectId('...') }
[
  { _id: ObjectId('...'), sku: 'PHONE-002', title: 'Smartphone Y', specs: { screen: { type: 'AMOLED' } } }
]
[
  { _id: ObjectId('...'), sku: 'PHONE-002', specs: { battery: { capacity: '5000mAh', fastCharging: true } } }
]
{ acknowledged: true, matchedCount: 1, modifiedCount: 1 }

النتيجة: تستهدف صيغة النقطة الحقول المتداخلة متعددة المستويات بدقة؛ ولا تؤثر الاستعلامات وعمليات التحديث إلا على الحقول المستهدفة ولا تحل محل الكائن المتداخل بأكمله.

▶ المثال 2: تطبيق عملي شامل لـ $elemMatch وتحديثات المصفوفات

JAVASCRIPT
// Scene:ShopHub Product Review Management
db.products.insertOne({
  sku: 'LAPTOP-001',
  title: 'Laptop Pro',
  reviews: [
    { userId: 'user_010', rating: 2, content: 'Poor quality', helpful: 0, createdAt: new Date('2026-05-01') },
    { userId: 'user_011', rating: 5, content: 'Excellent good value', helpful: 30, createdAt: new Date('2026-06-01') },
    { userId: 'user_012', rating: 4, content: 'Good performance', helpful: 12, createdAt: new Date('2026-07-01') }
  ]
});

// 1. Exact Search:The Same Comment rating>=4 and includes 'good'
db.products.find({
  reviews: { $elemMatch: { rating: { $gte: 4 }, content: /good/i } }
});
// Hit only user_011 Comments on(rating=5 and includes "good")

// 2. Use $ to update the first top-rated review
db.products.updateOne(
  { sku: 'LAPTOP-001', "reviews.rating": { $gte: 5 } },
  { $set: { "reviews.$.featured": true } }
);

// 3. Use arrayFilters Mark all low-rated reviews
db.products.updateOne(
  { sku: 'LAPTOP-001' },
  { $set: { "reviews.$[low].flagged": true } },
  { arrayFilters: [{ "low.rating": { $lt: 3 } }] }
);

// 4. Delete all low-rated reviews
db.products.updateOne(
  { sku: 'LAPTOP-001' },
  { $pull: { reviews: { rating: { $lt: 3 } } } }
);

الإخراج:

TEXT 📖 للعرض فقط
{ acknowledged: true, insertedId: ObjectId('...') }
[
  { _id: ObjectId('...'), sku: 'LAPTOP-001', reviews: [{ userId: 'user_011', rating: 5, content: 'Excellent good value', helpful: 30 }] }
]
{ acknowledged: true, matchedCount: 1, modifiedCount: 1 }
{ acknowledged: true, matchedCount: 1, modifiedCount: 1 }
{ acknowledged: true, matchedCount: 1, modifiedCount: 1 }

النتيجة: تتطابق $elemMatch تمامًا مع التعليق نفسه؛ $ يقوم بتحديث أول نتيجة مطابقة؛ arrayFilters يقوم بإجراء تحديث جماعي بناءً على الشروط؛ $pull يحذف التعليقات التي تستوفي الشروط.

JAVASCRIPT
// === Creating an Array Field Index ===
db.products.createIndex({ tags: 1 });
// Automatically become multikey index

// === Composite multikey index ===
db.products.createIndex({ category: 1, tags: 1 });

// === View Index ===
db.products.getIndexes();

▶ المثال 3: تمرين عملي شامل يجمع بين المصفوفات والوثائق المتداخلة

JAVASCRIPT
// Complete Scene:Nested Queries for E-commerce Product Reviews
// 1. Preparing the Data:Products with nested reviews
db.products.insertOne({
  sku: 'PHONE-001',
  title: 'Smartphone X',
  specs: {
    screen: { size: '6.5', type: 'OLED' },
    battery: { capacity: '4500mAh', type: 'Li-Po' }
  },
  reviews: [
    { userId: 'user_001', rating: 5, content: 'Excellent phone! Great battery', helpful: 15, createdAt: new Date('2026-06-01') },
    { userId: 'user_002', rating: 3, content: 'Good but expensive', helpful: 5, createdAt: new Date('2026-06-15') },
    { userId: 'user_003', rating: 5, content: 'Best phone ever, amazing good quality', helpful: 25, createdAt: new Date('2026-07-01') }
  ]
});

// 2. Search:Rating >= 4 and includes 'good' Comments on Keywords(The same comment meets the criteria)
db.products.find({
  reviews: {
    $elemMatch: {
      rating: { $gte: 4 },
      content: /good/i
    }
  }
}, { sku: 1, title: 1, reviews: 1 });

// 3. Update:Feature the top-rated comment
db.products.updateOne(
  { sku: 'PHONE-001', 'reviews.rating': { $gte: 5 } },
  { $set: { 'reviews.$.featured': true } }
);

// 4. Query Array Elements:tags Includes '5g' And the array length = 3
db.products.find({ tags: { $all: ['5g', 'amoled'], $size: 3 } });

// 5. Multi-level nested queries:Screen Size = 6.5
db.products.find({ 'specs.screen.size': '6.5' });

الإخراج:

TEXT 📖 للعرض فقط
{ acknowledged: true, insertedId: ObjectId('...') }
[
  { _id: ObjectId('...'), sku: 'PHONE-001', title: 'Smartphone X', reviews: [{ userId: 'user_003', rating: 5, content: 'Best phone ever, amazing good quality', helpful: 25 }] }
]
{ acknowledged: true, matchedCount: 1, modifiedCount: 1 }
[
  { _id: ObjectId('...'), sku: 'PHONE-001', tags: ['5g', 'amoled', 'fast-charging'] }
]
[
  { _id: ObjectId('...'), sku: 'PHONE-001', specs: { screen: { size: '6.5' } } }
]

النتيجة: تُرجع المنتج PHONE-001؛ وفي المصفوفة reviews، لا يستوفي سوى التقييم الثالث الشرطين — rating >= 4 واحتواء التقييم على كلمة «good» — وهو ما يوضح تمامًا قدرة $elemMatch على إجراء المطابقة الدقيقة.


❓ أسئلة شائعة

س هل $elemMatch إلزامي؟
ج يكون إلزاميًا عندما يتعين على مصفوفة واحدة استيفاء شروط متعددة في آن واحد. أما إذا كان هناك شرط واحد فقط (مثل { tags: '5g' })، فلا حاجة إلى $elemMatch.
س ما الفرق بين الترميز بالنقطة و$elemMatch؟
ج قد يتطابق الترميز بالنقطة { "a.b": 1, "a.c": 2 } مع عناصر موجودة في نفس المستند ولكن من مصفوفات مختلفة؛ أما $elemMatch فيجب أن يتطابق مع عناصر من نفس المصفوفة.
س هل يمكن فهرسة حقول المصفوفات؟
ج نعم. يقوم MongoDB تلقائيًا بإنشاء فهارس متعددة المفاتيح لحقول المصفوفات، لكن الفهرس المركب لا يمكن أن يحتوي إلا على حقل مصفوفة واحد كحد أقصى.
س هل أداء استعلامات المستندات المتداخلة جيد؟
ج يعمل التداخل أحادي المستوى بشكل مشابه للحقول العادية. أما التداخل متعدد المستويات فيتطلب استخدام صيغة النقطة، لكن الفهارس تظل تعمل. نوصي بالحد من التداخل بحيث لا يتجاوز 3 مستويات.

📖 ملخص


📝 تمارين

  1. السؤال الأساسي (⭐): البحث عن المنتجات التي تتضمن علاماتها "5g" أو "amoled".
  2. المشكلة الأساسية (⭐): استخدم الأمر $pull لحذف جميع التعليقات التي حصلت على تقييم أقل من 2.
  3. مشكلة متقدمة (⭐⭐): استخدم $elemMatch للعثور على المنتجات في التعليقات التي «تبلغ تقييمها 4 أو أكثر وتحتوي على الكلمة المفتاحية "good"».
  4. تمرين متقدم (⭐⭐): استخدم العنصر النائب $ لتحديث الحقل helpful في تعليقات مستخدم معين.
  5. التحدي (⭐⭐⭐): تنفيذ ميزة «الإعجاب» (مفيد +1) في نظام التعليقات، وتصفية التعليقات ذات التقييم المنخفض، ووضع علامة «تمت مراجعته» على مجموعة من التعليقات دفعة واحدة.
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%