ใช้ $unwind แยกอาร์เรย์ แล้ว $group นับตามเงื่อนไข
Operator $unwind แยกอาร์เรย์ออกเป็นเอกสารแยกต่างหาก ทำให้สามารถประมวลผลแต่ละอิลิเมนต์ได้ แล้ว $group นับเฉพาะที่ตรงเงื่อนไข
ตัวอย่างข้อมูล (อาร์เรย์ซ้อน 2 ระดับ)
> db.demo478.insertOne({
Details: {
_id: 1,
Information: [
{ Name: "Chris", Age: 21 },
{ Name: "David", Age: 23 },
{ Name: null, Age: 22 },
{ Name: null, Age: 24 }
]
}
});
> db.demo478.insertOne({
Details: {
_id: 2,
Information: [
{ Name: "Bob", Age: 21 },
{ Name: null, Age: 20 }
]
}
});
Query $unwind และนับเฉพาะ Name ไม่เป็น null
> db.demo478.aggregate([
{ $unwind: "$Details.Information" },
{ $group: {
_id: "$Details.Information.Age",
count: { $sum: { $cond: [{ $gt: ["$Details.Information.Name", null] }, 1, 0] } }
}},
{ $sort: { count: -1 } }
]);
ผลลัพธ์
{ "_id": 21, "count": 2 }
{ "_id": 23, "count": 1 }
{ "_id": 24, "count": 0 }
{ "_id": 20, "count": 0 }
{ "_id": 22, "count": 0 }
คำอธิบาย
- $unwind: "$Details.Information" - แยกอาร์เรย์ Information เป็นเอกสารแยกต่างหาก (6 เอกสาร)
- $group - จัดกลุ่มตาม Age
- $cond: [{ $gt: ["$Details.Information.Name", null] }, 1, 0] - นับ 1 ถ้า Name ไม่เป็น null, ไม่นับถ้าเป็น null
- $sort: { count: -1 } - เรียงตามจำนวนมากไปน้อย
การนับแบบอื่นๆ
// นับทั้งหมด (รวม null)
{ $group: { _id: "$Details.Information.Age", count: { $sum: 1 } } }
// นับ distinct Name ต่อ Age
{ $group: { _id: "$Details.Information.Age", uniqueNames: { $addToSet: "$Details.Information.Name" } } },
{ $project: { _id: 1, count: { $size: "$uniqueNames" } } }
// ใช้ $facet นับหลายอย่างพร้อมกัน (MongoDB 3.4+)
{ $facet: {
total: [{ $count: "total" }],
nonNull: [{ $match: { "Details.Information.Name": { $ne: null } } }, { $count: "nonNull" }]
} }