เข้าใจ MongoDB Aggregation Pipeline แบบประมวลผลข้อมูลทีละ Stage
เรียนรู้แนวคิด $match, $project, $group, $sort และ stage อื่น ๆ เพื่อกรอง แปลง และสรุปข้อมูลในฐานข้อมูลโดยไม่ย้ายงานทั้งหมดไปทำในแอป

ภาพรวม
Aggregation Pipeline ใน MongoDB คือทางเดินประมวลผลข้อมูลทีละด่าน นึกภาพเหมือนเอาเอกสารจำนวนมากเทลงสายพาน แล้วให้แต่ละสถานีทำงานคนละอย่าง กรอง จัดกลุ่ม คำนวณ เรียง ตัดฟิลด์ สุดท้ายได้ผลลัพธ์ที่สรุปแล้วออกมา 🙂
ถ้าใน SQL เราเขียนประมาณนี้ SELECT status, COUNT(*) FROM orders GROUP BY status; ใน MongoDB เราจะคิดเป็น pipeline แบบนี้ เริ่มจาก collection orders แล้วส่งเอกสารผ่าน stage $group เพื่อรวมข้อมูลตาม status
ตัวอย่างง่ายมาก orders.aggregate([ { $group: { _id: "$status", total: { $sum: 1 } } } ]) ความหมายคือ เอาค่า status มาเป็นกุญแจของกลุ่ม เก็บไว้ใน _id แล้วนับจำนวนเอกสารในแต่ละกลุ่มด้วย $sum: 1
ผลลัพธ์อาจหน้าตาประมาณนี้ { _id: "paid", total: 120 } { _id: "pending", total: 18 } { _id: "cancelled", total: 7 } นี่คือ GROUP BY แบบ MongoDB ชัด ๆ แค่เปลี่ยนจากตารางและแถว มาเป็น collection และ document
ถ้าอยากสรุปยอดขายตามลูกค้า ใน SQL อาจเป็น SELECT customerId, SUM(amount) FROM orders GROUP BY customerId; ใน MongoDB คือ orders.aggregate([ { $group: { _id: "$customerId", revenue: { $sum: "$amount" } } } ]) สังเกตว่า "$amount" หมายถึงอ่านค่าจาก field amount ไม่ใช่ string ธรรมดา
Pipeline เก่งตรงที่ต่อหลายด่านได้ เช่นอยากนับเฉพาะออเดอร์ที่จ่ายเงินแล้ว เรียงจากยอดมากไปน้อย orders.aggregate([ { $match: { status: "paid" } }, { $group: { _id: "$customerId", revenue: { $sum: "$amount" } } }, { $sort: { revenue: -1 } }, { $limit: 10 } ]) อ่านเป็นภาษาคนคือ กรอง paid ก่อน รวมยอดตาม customerId เรียงยอดสูงสุดก่อน เอาแค่ 10 อันดับแรก
จุดสำคัญคือ $match ควรวางให้เร็วที่สุดเท่าที่ทำได้ เพราะยิ่งกรองก่อน ข้อมูลที่ไหลไป stage ถัดไปยิ่งน้อย เร็วขึ้น ใช้ index ได้ดีขึ้น เหมือน SQL ที่ WHERE ก่อน GROUP BY นั่นแหละ
$group ไม่ได้มีแค่ $sum ยังมี $avg สำหรับค่าเฉลี่ย $min ค่าน้อยสุด $max ค่าสูงสุด $first ค่าแรกในกลุ่ม $push เก็บค่าหลายรายการเป็น array เช่นสรุปยอดเฉลี่ยต่อหมวดสินค้า { $group: { _id: "$category", avgPrice: { $avg: "$price" } } }
อีก stage ที่ใช้บ่อยคือ $project ใช้จัดหน้าตาผลลัพธ์ เปลี่ยนชื่อ field ซ่อน field ที่ไม่ต้องการ หรือคำนวณ field ใหม่ เช่นหลัง group แล้วไม่อยากใช้ชื่อ _id ก็ project ออกมาเป็น category แทน
Aggregation Pipeline จึงเหมาะกับงาน report dashboard สถิติผู้ใช้ ยอดขายรายวัน การจัดอันดับ และการแปลงข้อมูลก่อนส่งให้ API โดยไม่ต้องดึงข้อมูลทั้งหมดมา loop ในแอปเอง
สรุปสั้น ๆ ถ้า find() คือการหยิบเอกสาร Aggregation คือการเอาเอกสารไปผ่านโรงงานประมวลผล ส่วน $group คือหัวใจของการทำ SQL GROUP BY ในโลก MongoDB เข้าใจ $match + $group + $sort + $project ก็เริ่มทำรายงานจริงได้เยอะมากแล้ว 🚀
แนวทางนำไปใช้
- นำแนวคิดจากโพสต์นี้ไปทดลองกับงานจริงของคุณ
- แยกเป็นขั้นตอนเล็ก ๆ แล้วทำทีละส่วน
- บันทึกผลลัพธ์และสิ่งที่เรียนรู้เพื่อต่อยอด
สรุป
เรียนรู้แนวคิด $match, $project, $group, $sort และ stage อื่น ๆ เพื่อกรอง แปลง และสรุปข้อมูลในฐานข้อมูลโดยไม่ย้ายงานทั้งหมดไปทำในแอป