این فصل توضیح مفصلی از تجزیه و تحلیل آماری MongoDB را معرفی می‌کند که اصلی‌ترین قسمت آن از طریق "Aggregation Pipeline" به دست می‌آید. این مانند دستور "group by" در SQL است. در پوسته MongoDB، تجزیه و تحلیل آماری با استفاده از تابع 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>: <ترتیب مرتب سازی>, <field2>: <ترتیب مرتب سازی> ... } }

توضیحات:

  • ، - نام فیلدهای مورد نظر برای مرتب‌سازی، از مرتب‌سازی چندگانه پشتیبانی می‌کند.
  • <ترتیب مرتب سازی> - جهت مرتب سازی، -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.
                   ])