Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MongoDB

MongoDB Group By Date นับจำนวนวันที่ซ้ำด้วย Aggregation

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

  1. $group: สร้าง Composite Key จาก dayOfYear + year*400 เพื่อ Unique ต่อวัน (Ignore Time)
  2. Frequency: {$sum: 1}: นับจำนวน Doc ต่อ Group
  3. d: {$min: "$DueDate"}: เก็บ Date ตัวแรกของ Group ไว้แสดงผล
  4. $sort: {_id: 1}: เรียงตาม Key (chronological)
  5. $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 } }
]);