فصل جدید، فریم‌ورک Aggregation

Aggregation Framework

25 اردیبهشت 1401
درسنامه درس 66 از سری دوره جامع آموزش MongoDB
MongoDB: فصل جدید، فریم ورک Aggregation (قسمت 68)

تا به حال تمام کوئری های خود برای دریافت داده را با متد های find و findOne می نوشتیم اما برخی اوقات دریافت داده ها باید آنقدر شخصی سازی شود و اینقدر جزئی یا با تفاسیر خاص باشد که متد های Find و findOne به درد ما نمی خورند. در اینجاست که فریم ورک aggregation وارد کار می شود و به ما اجازه می دهد که داده ها را دقیقا به شکل مورد نظر خودمان دریافت کنیم. به زبان ساده شما می توانید فریم ورک aggregation را یک حالت پیشرفته تر از find بدانید. این فریم ورک مسیر خاصی را برای داده های دریافت شده از کالکشن شما تعریف می کند و داده ها در هر مرحله از این مسیر دچار تغییر می شوند. هر مرحله، داده های تغییر یافته از مرحله قبل را دریافت می کند بنابراین می توانیم مراحل تکراری نیز داشته باشیم. مثلا داده ها را با match$ از کالکشن دریافت کنیم و سپس دوباره match$ را روی آن ها صدا بزنیم تا دوباره آن ها را فیلتر کنیم.

برای شروع این جلسه از یک پایگاه داده آماده ای استفاده می کنیم که قبلا هم برایتان قرار داده بودم و از آن استفاده کرده بودیم. اگر آن را ندارید، می توانید دوباره از لینک زیر دانلودش کنید:

دانلود پایگاه داده آماده

پس از دانلود، یک ترمینال را در همان مسیر باز کرده و دستور زیر را در آن اجرا کنید:

mongoimport persons.json -d analytics -c persons --jsonArray

با اجرای این دستور 5000 سند به کالکشن persons در پایگاه داده analytics اضافه می شود. حالا وارد این پایگاه داده می شویم:

use analytics

سپس به جای استفاده از find می خواهیم از aggregate استفاده کنیم (هنوز اجرا نکنید):

db.persons.aggregate([])

همانطور که می بینید aggregate یک آرایه می گیرد. چرا آرایه؟ همانطور که گفتم aggregate یک مجموعه از مراحل مختلف است و داده ها در هر مرحله تغییر می کنند بنابراین باید آرایه باشد. در ضمن یادتان باشد که aggregate مانند find می تواند از ایندکس ها استفاده کند بنابراین زمانی که با aggregate کار می کنیم، بحث ایندکس ها کنار گذاشته نمی شود! بیایید یک مثال ساده بزنیم. من می خواهم به دنبال افراد مونث درون پایگاه داده بگردم:

db.persons.aggregate([ {$match: {gender: "female"}} ])

match$ دقیقا مانند آرگومان اول find است که داده ها را فیلتر می کرد بنابراین هر چیزی که آنجا یاد گرفتیم (انواع اپراتور های gt$ و تمام قوانین دیگر) در اینجا نیز صدق می کند. با اجرای این کوئری تمام اسنادی که مقدار gender در آن ها female باشد برگردانده می شوند. این اولین مرحله در فریم ورک aggregation است (به هر کدام از این مراحل stage می گوییم) اما من گفتم که می توانیم تعداد مراحل بسیار بیشتری داشته باشیم.

از آنجایی که تعداد این مراحل زیاد است و خواندن این دستورات بسیار طولانی می شود، من کوئری ها را به صورت باز شده قرار می دهم تا در هم نباشند و شما بهتر آن ها را بخوانید. مرحله بعدی در فریم ورک aggregation متد group$ است که داده ها را با هم در یک گروه قرار می دهد. مثلا من می گویم داده های برگردانده شده از match$ را بر اساس ایالت/استان دسته بندی کن. یادتان باشد که match$ فقط خانم ها را برمی گرداند بنابراین مرحله group$ روی همین خانم ها کار می کند:

db.presons.aggregate([
    { $match: { gender: 'female' } },
    { $group: { _id: { state: "$location.state" } } }
])
    .pretty()

زمانی که در حال کار با Group$ هستیم، اولین پارامتری که باید به آن پاس بدهیم، همیشه id_ است (فارغ از اینکه چه چیزی را می خواهید تغییر دهید). اینجا id_ مشخص می کند که می خواهید بر اساس چه معیاری داده ها را دسته بندی کنید بنابراین باید مبنای خود را به آن پاس بدهید. من state (به معنی ایالت) را پاس داده ام و گفته ام داده ها را بر اساس آن دسته بندی کن. البته شما می توانید به جای این state هر نام دیگری انتخاب کنید (state ای که به عنوان key است نه State ای که داخل رشته می باشد)، سپس مقدار location.state را پاس داده ایم اما باید علامت $ را نیز بزارید. علامت $ مشخص می کند که منظور ما از location همان location ای است که در داده های برگشتی از طرف match$ وجود دارد.

در مرحله بعد می توانیم به هر سند یک key اضافه کنیم و در آن key از اپراتور های accumulator استفاده کنیم. شما می توانید لیست کاملی از این اپراتور ها را از صفحه زیر دریافت کنید:

https://docs.mongodb.com/manual/reference/operator/aggregation/group/

من نام key اضافه شده را totalPersons می گذارم. از بین اپراتور ها نیز، اپراتور sum$ را می خواهم. مقدار پاس داده شده به sum$ مقداری است که به ازای هر سند دسته بندی شده به totalPersons می رسد. مثلا اگر 3 نفر داشته باشیم که از یک state باشند و مقدار Sum$ را روی 1 بگذاریم، آنگاه sum 3 واحد اضافه می شود.

db.persons.aggregate([
    { $match: { gender: "female" } },
    { $group: { _id: { state: "$location.state" }, totalPersons: { $sum: 1 } } }
])
    .pretty()

از آنجایی که از sum استفاده کرده ایم باید بدانید که نتیجه این دستور چیست. وقتی sum و group با هم می آیند باعث تجمیع سند ها می شوند. به طور مثال اگر 3 سند داشته باشیم که در آن ها state یکی باشد، این دستور هر سه سند را در یک سند ادغام می کند. به همین دلیل totalPersons را تعریف کرده ایم تا تعداد افراد هر استان را نمایش بدهد.

به نظر شما این کوئری چه نتیجه ای را به ما می دهد؟ در قسمت بعد در مورد نتیجه این کوئری صحبت خواهیم کرد.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری دوره جامع آموزش MongoDB توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

مقالات مرتبط
آخرین سوالات کاربران
5451218 در 3 سال قبل پرسیده:
ما را دنبال کنید
اینستاگرام روکسو تلگرام روکسو ایمیل و خبرنامه روکسو