Mongo认为10月1日和2日是不同的月份

问题描述

我需要获取一个月的所有记录,例如,我创建了以下两个记录:

  • 2020年10月1日(2020- 09 -30T21:00:00.000 + 00:00)
  • 2020年10月5日(2020- 10 -04T21:00:00.000 + 00:00)

Example entries in the database

由于存储时间偏移了一个小时,我们看到它们属于不同的月份,但是当转换为Date(JavaScript)时,我们将获得正确的日期(01/10/2020和05/10/2020)。 / p>

但是Mongo 计算了不同月份的这两个字段,而我只得到一条记录。

查询示例:

.aggregate([
                {
                    $addFields: {
                        month: {$month: '$date'},},{
                    $match: {
                        month: Number(month),]);

解决方法

当您将日期保存到Mongo时,您可能已经注意到它被保存为ISODate而不是Date类型。首先让我们了解什么是ISODateISODate()是一个包装函数,它将所有日期转换为Mongo易于处理的单个表示形式。根据他们的docs中的规定:

默认情况下,MongoDB将时间存储在UTC中,并将所有本地时间表示形式转换为这种形式。

现在您不在UTC时区,我怎么知道?因为您的“正确”时间不是UTC表示的时间。

那么,为什么在javascript中进行转换时却获得了“正确的”时间?同样,根据时区,有很多方法和不同方法可以将Date对象转换为字符串。但是javascript使用您的机器时间(我想它会同步到您的时区)进行转换。

那你该怎么办?您需要调整时区间隔的汇总,假设所有记录都来自同一时区,您可以执行以下操作:

  • (在这种情况下,假设您比UTC早5个小时,因此我们想在Mongo日期前加上1000 * 60 * 60 * 5 = 18000000毫秒)
db.collection.aggregate([
    {
        "$addFields": {
            month: {
                $month: {
                    $add: [
                        "$date",18000000 // 5 hours in milliseconds
                    ]
                },}
        }
    },{
        $match: {
            month: Number(month)
        }
    }
]);

如果要从不同时区收集文档,则需要保存一个offset字段,以便将时间保存到数据库中以帮助进行计算。