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

المستندات والمجموعات في MongoDB

الدرس 2 من 8 · MongoDB

في قواعد البيانات العلائقية مثل MySQL، البيانات جداول بأعمدة ثابتة. أما في MongoDB فالبيانات مستندات مرنة، تشبه كثيراً الكائنات التي تعرفها في JavaScript. في هذا الدرس ستفهم شكل المستند بالتفصيل، والأنواع التي يمكن أن يحملها، وكيف تُنظَّم المستندات في مجموعات. وسنبني معاً قاعدة بيانات لمكتبة كتب.

هذا مستند كتاب كامل:

{
_id: ObjectId('6af3b81b855b5f32ecccd48d'),
title: 'رحلة إلى القمر',
author: 'سارة أحمد',
year: 2020,
pages: 180,
price: 75.5,
available: true,
genres: [ 'خيال علمي', 'مغامرات' ],
publisher: { name: 'دار النور', country: 'مصر' },
addedAt: ISODate('2026-09-01T00:00:00.000Z'),
notes: null
}

المستند مجموعة من الحقول (Fields)، وكل حقل: اسم ثم نقطتان ثم قيمة. تخيّله مثل بطاقة الكتاب في مكتبة قديمة: كل المعلومات عن الكتاب مكتوبة في بطاقة واحدة متكاملة.

يُخزّن MongoDB المستندات داخلياً بصيغة اسمها BSON (اختصار Binary JSON)، وهي نسخة ثنائية من JSON تدعم أنواعاً إضافية مثل التواريخ.

النوع مثال من المستند ملاحظة
نص 'رحلة إلى القمر'
رقم صحيح 2020
رقم عشري 75.5
منطقي true
مصفوفة [ 'خيال علمي', 'مغامرات' ] قائمة قيم في حقل واحد
مستند متداخل { name: 'دار النور', country: 'مصر' } مستند داخل مستند
تاريخ ISODate('2026-09-01...') يُنشأ بـ new Date()
فارغ null
معرّف ObjectId('...') للحقل _id

لاحظ القوة هنا: المصفوفة والمستند المتداخل. في MySQL، لتخزين عدة تصنيفات لكتاب واحد تحتاج جدولاً منفصلاً وربطاً بـ JOIN. في MongoDB، تضعها في المستند نفسه مباشرة.

كل مستند في MongoDB يجب أن يحمل حقلاً اسمه _id، فريداً في مجموعته. إذا لم تضعه بنفسك، يولّده MongoDB تلقائياً من نوع ObjectId: رقم من 24 خانة ست عشرية مثل 6af3b81b855b5f32ecccd48d.

الطريف أن ObjectId يحتوي داخله وقت إنشائه. يمكنك استخراجه:

db.books.findOne()._id.getTimestamp()

فتعرف متى أُضيف المستند حتى دون حقل تاريخ! الـ _id مثل رقم الشحنة في شركة توصيل: فريد لكل شحنة، ويحمل في طياته معلومات عنها.

المستندات المتشابهة تُجمع في مجموعة، مثل books للكتب و authors للمؤلفين. المجموعة تقابل الجدول في MySQL، لكن مع فرق جوهري: لا تفرض شكلاً ثابتاً. يمكن أن يحتوي مستندان في نفس المجموعة على حقول مختلفة:

{ _id: 'sara-ahmed', name: 'سارة أحمد', country: 'مصر' }
{ _id: 'omar-khaled', name: 'عمر خالد', website: 'example.com', awards: 2 }

المؤلف الأول له دولة، والثاني له موقع وجوائز. هذه المرونة (Schema Flexibility) مفيدة جداً عندما تتطور بيانات تطبيقك باستمرار.

قاعدة البيانات والمجموعات في mongosh

Section titled “قاعدة البيانات والمجموعات في mongosh”
use library

ينتقل إلى قاعدة بيانات اسمها library. وإن لم تكن موجودة، تُنشأ تلقائياً عند إضافة أول مستند. ولعرض المجموعات:

show collections
db.getCollectionNames()
الناتج
[ 'books' ]

db تشير دائماً إلى قاعدة البيانات الحالية، و db.books إلى مجموعة الكتب فيها. وكما القاعدة، المجموعة تُنشأ تلقائياً عند أول إضافة.

عند تصميم المستندات، ستواجه سؤالاً دائماً: هل أضع البيانات المرتبطة داخل المستند، أم في مجموعة منفصلة وأشير إليها؟

  • التضمين (Embedding): مثل publisher داخل الكتاب. مناسب عندما تُقرأ البيانات معاً دائماً، وتكون صغيرة. قراءة واحدة تجلب كل شيء.
  • الإشارة (Referencing): مثل حقل authorId: 'sara-ahmed' يشير لمستند في مجموعة authors. مناسب عندما تكون البيانات كبيرة، أو مشتركة بين مستندات كثيرة، أو تتغير كثيراً.

القاعدة العامة في MongoDB: ما يُقرأ معاً يُخزَّن معاً.

صمم على الورق، ثم في mongosh إن أمكن، مستنداً لطالب في تطبيق مدرسي يحتوي:

  1. الاسم والعمر.
  2. مصفوفة بالمواد التي يدرسها.
  3. مستنداً متداخلاً للعنوان فيه المدينة والحي.
  4. تاريخ التسجيل.
  5. مصفوفة من المستندات للدرجات، مثل: { subject: 'رياضيات', score: 90 }.

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

  • أسماء حقول غير متسقة: name في مستند و Name في آخر يجعل البحث يفشل. اتفق على الأسماء.
  • أنواع غير متسقة: السنة 2020 رقماً في مستند و '2020' نصاً في آخر، فلا يجدهما نفس الاستعلام.
  • تضمين بيانات تكبر بلا حد: مستند MongoDB له حد أقصى للحجم (16 ميجابايت). لا تضع داخله مصفوفة تنمو للأبد، مثل كل تعليقات منشور مشهور.

سؤال

ماذا يحدث إذا أضفت مستنداً بدون حقل _id؟

سؤال

ما الفرق الأساسي بين المجموعة في MongoDB والجدول في MySQL؟

  • المستند حقول وقيم بصيغة تشبه JSON، ويُخزَّن داخلياً بصيغة BSON.
  • القيم قد تكون نصوصاً وأرقاماً وتواريخ، ومصفوفات ومستندات متداخلة أيضاً.
  • كل مستند له _id فريد، ويولّده MongoDB كـ ObjectId إن لم تحدده.
  • المجموعة تجمع المستندات المتشابهة دون فرض شكل ثابت، وتُنشأ تلقائياً.
  • «ما يُقرأ معاً يُخزَّن معاً»: ضمّن البيانات الصغيرة المرتبطة، وأشر للكبيرة والمشتركة.