Mongodb 如何按小时分组数据

Mongodb 如何按小时分组数据,mongodb,mongoose,mongodb-query,aggregation-framework,Mongodb,Mongoose,Mongodb Query,Aggregation Framework,即使数据不存在,如何在24小时内按每小时分组计数数据,即如果0将选择0 MonogDB 3.6 输入 [ { "_id": ObjectId("5ccbb96706d1d47a4b2ced4b"), "date": "2019-05-03T10:39:53.108Z", "id": 166, "update_at": "2019-05-03T02:45:36.208Z", "type": "image" }, { "_id": Obje

即使数据不存在,如何在24小时内按每小时分组计数数据,即如果0将选择0

MonogDB 3.6

输入

[
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2ced4b"),
    "date": "2019-05-03T10:39:53.108Z",
    "id": 166,
    "update_at": "2019-05-03T02:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2ced4c"),
    "date": "2019-05-03T10:39:53.133Z",
    "id": 166,
    "update_at": "2019-05-03T02:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2ced4d"),
    "date": "2019-05-03T10:39:53.180Z",
    "id": 166,
    "update_at": "2019-05-03T20:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2ced7a"),
    "date": "2019-05-10T10:39:53.218Z",
    "id": 166,
    "update_at": "2019-12-04T10:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2ced7b"),
    "date": "2019-05-03T10:39:53.108Z",
    "id": 166,
    "update_at": "2019-05-05T10:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2cedae"),
    "date": "2019-05-03T10:39:53.133Z",
    "id": 166,
    "update_at": "2019-05-05T10:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2cedad"),
    "date": "2019-05-03T10:39:53.180Z",
    "id": 166,
    "update_at": "2019-05-06T10:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2cedab"),
    "date": "2019-05-10T10:39:53.218Z",
    "id": 166,
    "update_at": "2019-12-06T10:45:36.208Z",
    "type": "image"
  }
]
  {
    "count": 0,
    "hour": "01" // 01 AM
  },
  {
    "count": 2,
    "hour": "02"
  },
  {
    "count": 0,
    "hour": "03"
  },
  {
    "count": 0,
    "hour": "04"
  },
  {
    "count": 0,
    "hour": "05"
  },
  {
    "count": 1,
    "hour": "20" // to 08 pm
  }
实施

db.collection.aggregate({
  $match: {
    update_at: {
      "$gte": "2019-05-03T00:00:00.0Z",
      "$lt": "2019-05-05T00:00:00.0Z"
    },
    id: {
      "$in": [
        166
      ]
    }
  }
},
{
  $group: {
    _id: {
      $substr: [
        "$update_at",
        11,
        2
      ]
    },
    count: {
      "$sum": 1
    }
  },

},
{
  $project: {
    _id: 0,
    hour: "$_id",
    count: "$count"
  }
},
{
  $sort: {
    hour: 1
  }
})
实际产出

{
    "count": 2,
    "hour": "02"
  },
  {
    "count": 1,
    "hour": "20"
  }
我的期望代码显示24小时事件数据为0或null,并将示例“02”转换为“02 AM”,“13”转换为“01 PM”:

预期产出

[
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2ced4b"),
    "date": "2019-05-03T10:39:53.108Z",
    "id": 166,
    "update_at": "2019-05-03T02:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2ced4c"),
    "date": "2019-05-03T10:39:53.133Z",
    "id": 166,
    "update_at": "2019-05-03T02:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2ced4d"),
    "date": "2019-05-03T10:39:53.180Z",
    "id": 166,
    "update_at": "2019-05-03T20:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2ced7a"),
    "date": "2019-05-10T10:39:53.218Z",
    "id": 166,
    "update_at": "2019-12-04T10:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2ced7b"),
    "date": "2019-05-03T10:39:53.108Z",
    "id": 166,
    "update_at": "2019-05-05T10:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2cedae"),
    "date": "2019-05-03T10:39:53.133Z",
    "id": 166,
    "update_at": "2019-05-05T10:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2cedad"),
    "date": "2019-05-03T10:39:53.180Z",
    "id": 166,
    "update_at": "2019-05-06T10:45:36.208Z",
    "type": "image"
  },
  {
    "_id": ObjectId("5ccbb96706d1d47a4b2cedab"),
    "date": "2019-05-10T10:39:53.218Z",
    "id": 166,
    "update_at": "2019-12-06T10:45:36.208Z",
    "type": "image"
  }
]
  {
    "count": 0,
    "hour": "01" // 01 AM
  },
  {
    "count": 2,
    "hour": "02"
  },
  {
    "count": 0,
    "hour": "03"
  },
  {
    "count": 0,
    "hour": "04"
  },
  {
    "count": 0,
    "hour": "05"
  },
  {
    "count": 1,
    "hour": "20" // to 08 pm
  }

以下是您可以测试的查询,用于MongoDB 4.0+

我将改进查询和更新

const query = [{
    $match: {
        update_at: {
            "$gte": ISODate("2019-05-03T00:00:00.0Z"),
            "$lt": ISODate("2019-05-05T00:00:00.0Z")
        },
        id: {
            "$in": [
                166
            ]
        }
    }
},
{
    $group: {
        _id: { $hour: "$update_at" },
        count: {
            "$sum": 1
        }
    },

},

{
    $addFields: {
        hourStr: { $toString: { $cond: { if: { $gte: ["$_id", 12] }, then: { $subtract: [12, { $mod: [24, '$_id'] }] }, else: "$_id" } } },
    }
},
{
    $project: {
        formated: { $concat: ["$hourStr", { $cond: { if: { $gt: ["$_id", 12] }, then: " PM", else: " AM" } }] },
        count: "$count",
        hour: 1,
    }
}]
没有“神奇”的解决方案,您必须将其硬编码到聚合中:

下面是一个使用Mongo v3.2+语法的示例,其中包含一些语法和魔法:

$addFields
阶段的简短解释:首先添加缺少的小时数,然后合并两个数组(原始找到的小时数和“新”缺少的小时数),最后转换为所需的输出(“01”到“01 AM”)

如果您使用的是Mongo v4+,我建议您将
$group
\u id
阶段更改为更一致的阶段

_id: {$hour: {$dateFromString: {dateString: "$update_at"}}}

如果这样做,您必须更新
$filter
$map
部分,以使用数字而不是字符串,并最终使用转换为您想要的格式,因此v4+要求。

您应该将日期值存储为
日期
对象,而不是字符串。我会这样做格式化:

db.collection.aggregate(
   [
      { $match: { ... } },
      {
         $group: {
            _id: { h: { $hour: "$update_at" } },
            count: { $sum: 1 }
         }
      },
      {
         $project: {
            _id: 0,
            hour: {
               $switch: {
                  branches: [
                     { case: { $lt: ["$_id.h", 10] }, then: { $concat: ["0", { $toString: "$_id.h" }, " AM"] } },
                     { case: { $lt: ["$_id.h", 13] }, then: { $concat: [{ $toString: "$_id.h" }, " AM"] } },
                     { case: { $lt: ["$_id.h", 22] }, then: { $concat: ["0", { $toString: { $subtract: ["$_id.h", 12] } }, " PM"] } },
                     { case: { $lt: ["$_id.h", 24] }, then: { $concat: [{ $toString: { $subtract: ["$_id.h", 12] } }, " PM"] } }
                  ]
               }
            },
            hour24: "$_id.h",
            count: 1
         }
      },
      { $sort: { hour24: 1 } }
   ])

作为非美国人,我不熟悉am/PM规则,尤其是午夜和中午的规则,但我想你已经掌握了原则。

如果你想以印度时间格式输出。然后下面的代码工作

    const query = [
    {
        $match: {
            update_at: {
                "$gte": ISODate("2019-05-03T00:00:00.0Z"),
                "$lt": ISODate("2019-05-05T00:00:00.0Z")
            },
            id: {
                "$in": [
                    166
                ]
            }
        }
    },
    {
        $project: {
            "h": { "$hour": { date: "$update_at", timezone: "+0530" } },
        }
    },
    {
        $group:
        {
            _id: { $hour: "$h" },
            count: { $sum: 1 }
        }
    }
];
尝试以下解决方案:

解释 我们按小时分组计算上传的图像数量

然后,我们添加额外的字段
hour
来创建时间间隔(如果您有v4.x,则有更好的时间间隔)

我们调整
hour
字段(将创建新文档),并将前两位数字拆分以匹配
count
,将后两位数字拆分以放置AM/PM时段



究竟为什么要将日期值存储为字符串而不是正确的
date
对象?12>的响应时间是13、14等。我想知道13点是下午1点,等等。怎么样?你在Mongo版本4.0+上吗?如果是这样的话,只需将
$addFields
阶段中的最终条件更改为强制转换为整数和减法12。不,我的mongo版本是3.*:(然后您必须硬编码转换。与我刚才在hoursOk to中所做的类似,我将等待它不,无法运行您的查询,因为我的mongodb服务器版本是3.*:(“Unrecognized expression$toInt”在Dom中,我的mongodb服务器版本是3.*,无法使用$toString。“Unrecognized expression'$toString”可能只是跳过它。如果没有“$concat仅支持字符串,而不支持int”。否则,似乎有一个解决方法:mongodb 4.2中的此查询测试