تقدم هذه الفصل شرحًا مفصلًا لتحليل MongoDB الإحصائي، يتم تحقيقه أساسًا من خلال أنبوب الربط (Aggregation Pipeline). وهو مشابه لعبارة "group by" في SQL. في MongoDB shell، يتم تنفيذ تحليل الإحصائيات باستخدام دالة db.collection.aggregate().

البرنامج التعليمي الأساسي

MongoDB Aggregation Pipeline

الخطوات العامة

  • استخدام $match لتصفية البيانات المستهدفة
  • استخدام $group لتجميع وحساب البيانات
  • استخدام $sort لفرز النتائج (اختياري)

البيانات التجريبية

البيانات في مجموعة orders كالتالي

{ _id: 1, cust_id: "abc1", ord_date: ISODate("2012-11-02T17:04:11.102Z"), status: "A", amount: 50 }
{ _id: 2, cust_id: "xyz1", ord_date: ISODate("2013-10-01T17:04:11.102Z"), status: "A", amount: 100 }
{ _id: 3, cust_id: "xyz1", ord_date: ISODate("2013-10-12T17:04:11.102Z"), status: "D", amount: 25 }
{ _id: 4, cust_id: "xyz1", ord_date: ISODate("2013-10-11T17:04:11.102Z"), status: "D", amount: 125 }
{ _id: 5, cust_id: "abc1", ord_date: ISODate("2013-11-12T17:04:11.102Z"), status: "A", amount: 25 }

دالة الربط

db.collection.aggregate(pipeline) الشرح:

  • يأخذ pipeline معلمة من نوع مصفوفة، حيث يمثل كل عنصر مرحلة معالجة.

المثال

db.orders.aggregate([
                     { $match: { status: "A" } },  // المرحلة الأولى
                     { $group: { _id: "$cust_id", total: { $sum: "$amount" } } },   // المرحلة الثانية
                     { $sort: { total: -1 } }  // المرحلة الثالثة
                   ])

SQL المكافئ

select sum(amount) as total from orders 
        where status="A" 
        group by cust_id 
        order by total desc

المرحلة $match

التنسيق:

{ $match: { <query> } }

الشرح:

  • <query> شروط استعلام MongoDB

يستخدم لتحديد شروط الاستعلام. إذا تم تجاهل $match، فإن ذلك يعني الاستعلام عن جميع البيانات.

نصيحة: إذا كنت لا تعرف بشكل جيد بتركيبيات الاستعلام في MongoDB، يرجى الرجوع إلى الفصول السابقة.

المرحلة $group

مشابهة لعبارة group by في SQL، يتم استخدامها لتجميع البيانات ثم إجراء سلسلة من الحسابات الإحصائية على البيانات المجمعة.

الاستخدام الأساسي للمرحلة $group

الصيغة:

{
  $group:
    {
      _id: <expression>, // شرط التجميع، على سبيل المثال: تجميع حسب أي حقل
      <field1>: { <accumulator1> : <expression1> },  // عملية التجميع، يمكنك إضافة N عمليات تجميع
      ...
    }
 }

الشرح:

  • - اسم المؤشر الإحصائي المخصص، يمكن أن يكون N في المجموع
  • - وظيفة التجميع، مشابهة لدوال الجمع والمتوسط وغيرها من وظائف التجميع في SQL، الفارق هو أن وظائف التجميع في MongoDB تأتي مسماة بـ $ كبادئة، على سبيل المثال: $sum، $avg
  • - معلمة وظيفة التجميع، عادة ما تكون قيمة الحقل المراد حسابها، يتم الإشارة إلى حقول المستند باستخدام التنسيق "$اسم الحقل"

مثال:

db.orders.aggregate([
                     {
					 	$group: { 
							_id: "$cust_id",
							total: { $sum: "$amount" }, // إضافة المؤشر الإحصائي الأول total، باستخدام عامل الجمع $sum
							amount_avg: {$avg: "$amount"}  // إضافة المؤشر الإحصائي الثاني avg، باستخدام مشغل الحساب المتوسط $avg
						} 
					}
               ])

الناتج:

{ "_id" : "abc1", "total" : 75, "amount_avg" : 37.5 }
{ "_id" : "xyz1", "total" : 250, "amount_avg" : 83.33333333333333 }

SQL المكافئ:

select 
	sum(amount) as  total,
	avg(amount) as amount_avg
from orders 
group by cust_id

وظائف التجميع $group

الوظائف الشائعة المستخدمة لتجميع $group كما يلي:

المشغل الوصف المثال
$avg حساب المتوسط {$avg: "$amount"}
$sum جمع {$sum: "$amount"}
$max القيمة القصوى {$max: "$amount"}
$min القيمة الصغرى {$min: "$amount"}
$first إرجاع البيانات بعد التجميع، محتوى الوثيقة الأولى {$first: "$amount"}
$last إرجاع البيانات بعد التجميع، محتوى الوثيقة الأخيرة {$last: "$amount"}
$push إرجاع البيانات بعد التجميع { $push: { ord_date: "$ord_date", amount: "$amount" }
$addToSet إرجاع البيانات بعد التجميع، يختلف عن $push حيث يزيل النسخ المكررة { $addToSet: "$amount" }

مثال على $push

db.orders.aggregate(
   [
     {
       $group:
         {
           _id: "$cust_id",
           all: { $push: { ord_date: "$ord_date", amount: "$amount" } } //قيم حقول ord_date و amount
         }
     }
   ]
)

الناتج

{ "_id" : "abc1", "all" : [ { "ord_date" : "2021-04-18 00:00:00", "amount" : 50 }, { "ord_date" : "2021-04-21 00:00:00", "amount" : 25 } ] }
{ "_id" : "xyz1", "all" : [ { "ord_date" : "2021-04-18 00:00:00", "amount" : 100 }, { "ord_date" : "2021-04-20 00:00:00", "amount" : 25 }, { "ord_date" : "2021-04-21 00:00:00", "amount" : 125 } ] }

مثال على $addToSet

db.orders.aggregate(
   [
     {
       $group:
         {
           _id: "$cust_id",
           all_amount: { $addToSet: "$amount" } //يعيد جميع قيم المبلغ المميزة
         }
     }
   ]
)

الناتج

{ "_id" : "abc1", "all_amount" : [ 25, 50 ] }
{ "_id" : "xyz1", "all_amount" : [ 100, 25, 125 ] }

$sort:

يتم وضع مرحلة $sort عادة في النهاية لفرز البيانات المجمعة.

الصيغة:

{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }

الشرح:

  • , - أسماء الحقول التي سيتم فرزها، يدعم عدة حقول.
  • - اتجاه الترتيب، -1 للتنازلي، 1 للتصاعدي.

مثال:

db.orders.aggregate([
                     { $match: { status: "A" } },
                     { $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
                     { $sort: { total: -1 } }
                   ])

ترقيم البيانات المجمعة

يمكننا تنفيذ ترقيم الصفحات باستخدام مشغلات $limit و $skip.

مثال:

db.orders.aggregate([
                     { $match: { status: "A" } },
                     { $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
                     { $sort: { total: -1 } },
					 { $limit: 5 }, // يحدد عدد السجلات المرجعية المُرجعة، مماثل لحجم الصفحة في الترقيم.
					 { $skip: 1 } // يتجاوز عددًا معينًا من السجلات، مماثل للإزاحة في SQL.
                   ])