在MongoDBShell中,如何查询某个时间段(比如一个月)的每日数据

In MongoDB Shell, How to query for day-by-day data for a time period (such as a month)

我想获取按 class(我的集合中的字段)分组的一天数据,持续一个月。

这是我试图查询的内容,但没有给出预期的输出。

查询:

db.collection.aggregate([
    // Get only records created in the last 30 days
    {$match:{
          "created_at":{$gt: new Date(ISODate().getTime() - 1000*60*60*24*30)},       
    }},

    // Get the year, month and day from the created_at TimeStamp
    {$project:{
          "year":{$year:"$created_at"}, 
          "month":{$month:"$created_at"}, 
          "day": {$dayOfMonth:"$created_at"}
    }}, 

    // Group by year, month and day and get the count
    {$group:{
          _id:{year:"$year", month:"$month", day:"$day"}, 
          "count":{$sum:1}
    }},

    // Group by class field
    { $group: {
          _id: "$meta.class", 
          total: {$sum: 1}
    }}  
])

预期输出:

{ "_id" : { "year" : 2021, "month" : 10, "day" : 01 }, "count" : {{ "_id" : "class1", "total" : 15 }, { "_id" : "class2", "total" : 25 }} }
{ "_id" : { "year" : 2021, "month" : 10, "day" : 02 }, "count" : {{ "_id" : "class2", "total" : 25 }, { "_id" : "class3", "total" : 10 }} }
...
{ "_id" : { "year" : 2021, "month" : 10, "day" : 30 }, "count" : {{ "_id" : "class3", "total" : 50 }} }

所以,有人可以告诉我如何达到预期的结果或者我做错了什么吗? 谢谢。

---编辑---

示例数据:

mongoplayground link : here

[
  {
    "key": 1,
    "_id": ObjectId("615602280000000000000000"),
    "created_at": ISODate("2021-09-30T18:30:00.000Z"),
    "meta": {
      "class": "class1",
      
    }
  },
  {
    "key": 2,
    "_id": ObjectId("615753a80000000000000000"),
    "created_at": ISODate("2021-10-01T18:30:00.000Z"),
    "meta": {
      "class": "class1",
      
    }
  },
  {
    "key": 3,
    "_id": ObjectId("615764100000000000000000"),
    "created_at": ISODate("2021-10-01T19:40:00.000Z"),
    "meta": {
      "class": "class1",
      
    }
  },
  {
    "key": 4,
    "_id": ObjectId("615776d00000000000000000"),
    "created_at": ISODate("2021-10-01T21:00:00.000Z"),
    "meta": {
      "class": "class2",
      
    }
  }
]

样本o/p:

[
   {
      "_id":{
         "year":2021,
         "month":10,
         "day":1
      },
      "count":[
         {
            "_id":"class1",
            "total":1
         }
      ]
   },
   {
      "_id":{
         "year":2021,
         "month":10,
         "day":2
      },
      "count":[
         {
            "_id":"class1",
            "total":2
         },
         {
            "_id":"class2",
            "total":1
         }
      ]
   }
]

试试这个:

db.collection.aggregate([
   { $match: { created_at: { $gt: moment().startOf('day').subtract(30, 'day').toDate() } } },
   {
      $group: {
         _id: {
            day: { $dateTrunc: { date: "$created_at", unit: "day" } },
            class: "$meta.class"
         },
         total: { $count: {} }
      }
   },
   {
      $group: {
         _id: "$_id.day",
         count: { $push: { total: "$total", class: "$_id.class" } }
      }
   }
])

每当我必须使用 date/time 值时,我建议使用 moment.js 库。

$dateTrunc() 需要 MongoDB 5.0 版。如果您喜欢或需要 year/month/day 部分,那么修改聚合管道的方法应该很明显。