ধরুন admin জানতে চায়: গত মাসে কোন খাবারটা সবচেয়ে বেশি বিক্রি হয়েছে, মোট কত টাকার বিক্রি, দিনপ্রতি গড় কত। এই হিসাব যদি কোডে করতে যান, তাহলে হাজার হাজার order টেনে এনে নিজে যোগ-বিয়োগ করতে হবে - ধীরও, জটিলও। Aggregation pipeline দিয়ে এই হিসাবটা database-কেই করিয়ে নেওয়া যায়, ধাপে ধাপে।
Pipeline মানে ধাপের সারি
নামেই বোঝা যাচ্ছে - data একটা পাইপ দিয়ে যায়, প্রতিটা ধাপ (stage) তার উপর একটা কাজ করে। $match অপ্রয়োজনীয় data ছাঁটাই করে (SQL-এর WHERE-এর মতো), $group দল বেঁধে হিসাব করে, $sort সাজায়, $project বেছে নেয় কোন field যাবে, আর $lookup অন্য collection থেকে data জোড়া লাগায় (JOIN-এর কাছাকাছি)।
db.orders.aggregate([
// ১. শুধু এই মাসের delivered order
{ $match: { status: "delivered", createdAt: { $gte: monthStart } } },
// ২. items array খুলে প্রতিটা item আলাদা সারি বানানো
{ $unwind: "$items" },
// ৩. product ধরে দল বেঁধে হিসাব
{ $group: {
_id: "$items.name",
totalQty: { $sum: "$items.qty" },
revenue: { $sum: { $multiply: ["$items.qty", "$items.price"] } }
} },
// ৪. বেশি বিক্রি আগে
{ $sort: { totalQty: -1 } },
{ $limit: 5 }
]);সবচেয়ে গুরুত্বপূর্ণ অভ্যাস: $match যত আগে বসাবেন, তত ভালো। প্রথম ধাপেই data ছেঁটে ফেললে বাকি ধাপগুলো কম data নিয়ে কাজ করে - pipeline দ্রুত হয়। ঠিক একই কারণে যেই field দিয়ে match বা group করবেন, সেগুলোতে index থাকলে সোনায় সোহাগা। আরেকটা কথা - pipeline বড় হলে কোডে ধাপে ধাপে comment রাখুন, নইলে ছয় মাস পরে নিজের লেখাই নিজে বুঝবেন না।
সবাই যে ভুলটা করে
Aggregation এড়িয়ে সব data কোডে টেনে এনে JavaScript দিয়ে হিসাব করা। Data ছোট থাকলে টের পাওয়া যায় না, কিন্তু order লাখ ছাড়ালেই API কয়েক সেকেন্ড আটকে থাকে আর memory খেয়ে ফেলে। হিসাবের কাজটা database-এর - ওটাই তার জন্য তৈরি।
আজকের Practice
আপনার orders collection দিয়ে তিনটা report বানান aggregation দিয়ে: (১) দিন অনুযায়ী মোট বিক্রি, (২) সবচেয়ে বেশি বিক্রি হওয়া ৫টা আইটেম, (৩) সবচেয়ে বেশি order করা ৫ জন customer। প্রতিটার আগে নিজে কাগজে লিখুন কোন কোন stage লাগবে।
Interview-এ কীভাবে বলবেন
Aggregation pipeline দিয়ে আমি জটিল report database-তেই বানাই - match দিয়ে আগে ছাঁটি, group দিয়ে হিসাব, sort-limit দিয়ে ফল সাজাই। এতে network দিয়ে কাঁচা data টানতে হয় না, আর match প্রথমে রাখায় pipeline দ্রুত থাকে।