Aggregation Pipeline ใน MongoDB รองรับการ Group By Date และนับ Frequency ได้ผ่าน Stage $group ร่วมกับ Date Operators เนื้อหานี้สาธิตการนับจำนวนเอกสารที่มี DueDate ซ้ำกัน โดย Group ตาม วัน/เดือน/ปี (Ignore Time)
ตัวอย่างข้อมูลทดสอบ
> db.demo160.insertOne({"DueDate": new ISODate()});
{ "acknowledged" : true, "insertedId" : ObjectId("5e357525fdf09dd6d0853a04") }
> db.demo160.insertOne({"DueDate": new ISODate("2019-01-11")});
{ "acknowledged" : true, "insertedId" : ObjectId("5e357532fdf09dd6d0853a05") }
> db.demo160.insertOne({"DueDate": new ISODate()});
{ "acknowledged" : true, "insertedId" : ObjectId("5e357534fdf09dd6d0853a06") }
> db.demo160.insertOne({"DueDate": new ISODate("2019-01-11")});
{ "acknowledged" : true, "insertedId" : ObjectId("5e357538fdf09dd6d0853a07") }
> db.demo160.insertOne({"DueDate": new ISODate("2020-04-10")});
{ "acknowledged" : true, "insertedId" : ObjectId("5e357542fdf09dd6d0853a08") }
แสดงข้อมูลเดิม (มี Time Component)
> db.demo160.find();
{
"_id" : ObjectId("5e357525fdf09dd6d0853a04"),
"DueDate" : ISODate("2020-02-01T12:55:01.983Z")
}
{
"_id" : ObjectId("5e357532fdf09dd6d0853a05"),
"DueDate" : ISODate("2019-01-11T00:00:00Z")
}
{
"_id" : ObjectId("5e357534fdf09dd6d0853a06"),
"DueDate" : ISODate("2020-02-01T12:55:16.787Z")
}
{
"_id" : ObjectId("5e357538fdf09dd6d0853a07"),
"DueDate" : ISODate("2019-01-11T00:00:00Z")
}
{
"_id" : ObjectId("5e357542fdf09dd6d0853a08"),
"DueDate" : ISODate("2020-04-10T00:00:00Z")
}
Aggregation Pipeline Group By Date
> db.demo160.aggregate([
{ $group: {
_id: {
$add: [
{ $dayOfYear: "$DueDate" },
{ $multiply: [400, { $year: "$DueDate" }] }
]
},
Frequency: { $sum: 1 },
d: { $min: "$DueDate" }
}},
{ $sort: { _id: 1 } },
{ $limit: 100 },
{ $project: { date: "$d", Frequency: 1, _id: 0 } }
]);
ผลลัพธ์ (Group By Date Only, Ignore Time)
{
"Frequency" : 2,
"date" : ISODate("2019-01-11T00:00:00Z")
}
{
"Frequency" : 2,
"date" : ISODate("2020-02-01T12:55:01.983Z")
}
{
"Frequency" : 1,
"date" : ISODate("2020-04-10T00:00:00Z")
}
คำอธิบาย Pipeline
$group: สร้าง Composite Key จากdayOfYear + year*400เพื่อ Unique ต่อวัน (Ignore Time)Frequency: {$sum: 1}: นับจำนวน Doc ต่อ Groupd: {$min: "$DueDate"}: เก็บ Date ตัวแรกของ Group ไว้แสดงผล$sort: {_id: 1}: เรียงตาม Key (chronological)$project: จัดรูปแบบ Output ให้เป็นdateและFrequency
วิธีง่ายกว่า (MongoDB 3.6+ ใช้ $dateTrunc)
db.demo160.aggregate([
{ $group: {
_id: { $dateTrunc: { date: "$DueDate", unit: "day" } },
Frequency: { $sum: 1 }
}},
{ $sort: { _id: 1 } },
{ $project: { date: "$_id", Frequency: 1, _id: 0 } }
]);