تا اینجای کار موفق شده ایم که داده های خودمان را به انواع دیگر داده تبدیل کنیم و آن ها را تا حد زیادی شخصی سازی کنیم تا طبق سلیقه و نیاز ما نمایش داده شوند اما هنوز اپراتور های دیگری داریم که باید با آن ها آشنا شویم. isoWeekYear$ یکی از این اپراتور ها است. اپراتور isoWeekYear$ یک تاریخ را گرفته و سپس سال را از آن جدا کرده و به ما پس می دهد. مثلا برای استفاده از آن می توانیم تعداد افراد متولد هر سال در پایگاه داده خود را محاسبه کنیم. چطور؟ ما می توانیم از یک Group استفاده کرده و سپس تمام داده های خود را بر اساس سال تولد گروه بندی کنیم. اینگونه مشخص می شود که در هر سال چند نفر متولد شده اند. برای انجام این کار باید یک Stage دیگر از نوع Group در انتهای کوئری خود اضافه کنیم:
db.persons.aggregate([ { $project: { _id: 0, name: 1, email: 1, birthdate: { $toDate: "$dob.date" }, age: "$dob.age", location: { type: "point", coordinates: [ { $convert: { input: "$location.coordinates.longitude", to: "double", onError: 0.0, onNull: 0.0 } }, { $convert: { input: "$location.coordinates.latitude", to: "double", onError: 0.0, onNull: 0.0 } } ] } } }, { $project: { gender: 1, email: 1, location: 1, age: 1, birthdate: 1, fullName: { $concat: [{ $toUpper: { $substrCP: ["$name.first", 0, 1] } }, { $substrCP: ["$name.first", 1, { $subtract: [{ $strLenCP: "$name.first" }, 1] }] }, " ", { $toUpper: { $substrCP: ["$name.last", 0, 1] } }, { $substrCP: ["$name.last", 1, { $subtract: [{ $strLenCP: "$name.last" }, 1] }] }] } } }, { $group: { _id: { birthYear: { $isoWeekYear: "$birthdate" } }, numPersons: { $sum: 1 } } } ]).pretty()
دو stage قبلی داده ها را فیلتر کرده و به شکل مرتب به ما تحویل می دهند و ما نیز در Stage سوم آن ها را دریافت می کنیم. برای group اول از همه یک id_ قرار می دادیم و سپس فیلدی را به آن پاس می دادیم که معیار دسته بندی ما است. من می خواهم داده ها را بر اساس سال تولد دسته بندی کنم بنابراین یک فیلد جدید به نام birthYear (به معنی «سال تولد») را ایجاد کرده ام. مقدار این فیلد، همان مقداری است که توسط اپراتور isoWeekYear$ برگردانده شود. اگر به کد بالا توجه کنید، متوجه خواهید شد که isoWeekYear$ فیلد birthdate (تاریخ تولد) را گرفته و سال را از آن جدا می کند. سپس یک فیلد جدید به نام numPersons داریم که با استفاده از sum$ کار می کند. اگر از چند جلسه قبل یادتان باشد sum$ تمام سند های ما را در هم ادغام می کرد و به ازای آن x واحد را به numPersons اضافه می کرد به طوری که x همان عدد پاس داده شده به sum$ باشد. مثلا اگر به sum$ عدد 5 را پاس می دادیم به ازای هر نفر 5 واحد به numPersons اضافه می کرد. نتیجه اجرای کوئری بالا به شکل زیر است (من فقط قسمتی از داده ها را می آورم):
{ "_id" : { "birthYear" : NumberLong(1989) }, "numPersons" : 93 } { "_id" : { "birthYear" : NumberLong(1953) }, "numPersons" : 97 } { "_id" : { "birthYear" : NumberLong(1965) }, "numPersons" : 98 } { "_id" : { "birthYear" : NumberLong(1946) }, "numPersons" : 100 } { "_id" : { "birthYear" : NumberLong(1952) }, "numPersons" : 85 } { "_id" : { "birthYear" : NumberLong(1981) }, "numPersons" : 102 } { "_id" : { "birthYear" : NumberLong(1996) }, "numPersons" : 86 } { "_id" : { "birthYear" : NumberLong(1947) }, "numPersons" : 93 } { "_id" : { "birthYear" : NumberLong(1956) }, "numPersons" : 87 } { "_id" : { "birthYear" : NumberLong(1950) }, "numPersons" : 99 } { "_id" : { "birthYear" : NumberLong(1963) }, "numPersons" : 98 } { "_id" : { "birthYear" : NumberLong(1975) }, "numPersons" : 107 } { "_id" : { "birthYear" : NumberLong(1993) }, "numPersons" : 110 }
بنابراین مشخص می شود که در هر سال چند نفر به دنیا آمده اند! احتمالا می گویید با این کار Stage های قبلی از بین می روند و کل کار بیهوده می شود. حرفتان درست است! این مثال فقط جهت یادگیری بود و در برنامه های واقعی نباید پس از اعمال عملیات های پیچیده روی داده ها آن ها را از بین ببریم! من از عمد داده های مراحل قبل را وارد این مرحله نکردم تا داده های برگشتی واضح باشد.
تنها مسئله ای که باقی می ماند، به هم ریخته بودن این داده ها است. بهتر است آن ها را با اضافه کردن یک Stage جدید، sort کنیم:
// بقیه کد ها دست نخورده باقی می مانند // { $group: { _id: { birthYear: { $isoWeekYear: "$birthdate" } }, numPersons: { $sum: 1 } } }, { $sort: { numPersons: -1 } } ]).pretty()
در اینجا گفته ام داده ها را بر اساس تعداد افراد متولد شده در هر سال (numPersons) مرتب کن و حالت آن را نیز روی نزولی (descending) قرار بده تا سالی که متولدین بالاتری داشته اول باشد و سالی که کمترین متولدین را داشته آخر باشد. با اجرای کوئری بالا نتیجه زیر را می گیریم (من فقط قسمتی از داده ها را می آورم):
{ "_id" : { "birthYear" : NumberLong(1955) }, "numPersons" : 113 } { "_id" : { "birthYear" : NumberLong(1961) }, "numPersons" : 111 } { "_id" : { "birthYear" : NumberLong(1960) }, "numPersons" : 110 } { "_id" : { "birthYear" : NumberLong(1993) }, "numPersons" : 110 } { "_id" : { "birthYear" : NumberLong(1975) }, "numPersons" : 107 } { "_id" : { "birthYear" : NumberLong(1945) }, "numPersons" : 106 } { "_id" : { "birthYear" : NumberLong(1976) }, "numPersons" : 105 }
بنابراین بیشترین افراد در سال 1995 متولد شده اند.
نکته نهایی که باید بررسی کنیم، تفاوت بین project$ و group$ است:
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.