当您将 unix 时间存储为时间戳时,如何对过去 12 个月的文档进行分组?

How to group documents for the last 12 months, month wise when you have unix time stored as timeStamp?

我有一个集合,其中数据每天根据 unix 纪元时间更新。例如:

{ 
    "uID" : "12345678", 
    "midNightTimeStamp" : NumberInt(1645381800), // 21st Feb 2022 midnight IST
    "energyConsumed" : NumberInt(53)
},
{ 
    "uID" : "12345678", 
    "midNightTimeStamp" : NumberInt(1645641000), // 24th Feb 2022 midnight IST
    "energyConsumed" : NumberInt(30)
}

现在如果您想按月查询最近 12 个月的数据,您会采用什么方法来解决这个问题?我所知道的是,我可以像这样在聚合查询中对数据进行分组:

 $project: {
            energyConsumed: 1.0,
            year: {
              $year: // How would you convert this from epoch
            },
            month: {
              $month: // How would you convert this from epoch
            }
          },

现在,如果我想将过去 12 个月的数据分组为这样的东西

  $group: {
            _id: '$month',
            energyConsumed: {
              $sum: '$energyConsumed'
            }
          }

我想要的输出是:

{
  id: 04 // (something like 04 or just April but data should be sorted month and year wise April 2021),
  energyConsumed: 4179772
},
{
  id: 05 // (something like 05 or just May but data should be sorted month and year wise),
  energyConsumed: 6179772
},
...
...
{
  id: 03 // (something like 03 or just March (March 2022),
  energyConsumed: 5643772
}

也许是这样:

 db.collection.aggregate([
 {
   $group: {
    _id: {
      $dateToString: {
       format: "%Y-%m",
        date: {
          $toDate: {
          "$multiply": [
            "$midNightTimeStamp",
            1000
          ]
        }
      }
     }
     },
     monthlyConsumption: {
       $sum: "$energyConsumed"
     }
    }
   }
 ])

解释:

$group 基于Year-Month ("YYYY-mm" ) 提取的midNightTimeStamp 字段和$sum 每月消费

playground

要赶上从现在开始的最后 12 个月,请将其放在上面 $group 阶段的前面:

// Back up one year from right now:                                                                           
var sdate = new ISODate();
sdate.setYear((sdate.getYear()-1) + 1900);

db.foo.aggregate([
    {$match: {$expr: {$gt:[{$toDate: {$multiply:['$midNightTimeStamp',1000]}},sdate]} } },
    {$group: { ... // as above

如果您 运行 已经 MongoDB 版本 5.0 那么您可以使用 $dateTrunc:

db.collection.aggregate([
  {
    $group: {
      _id: {
        $dateTrunc: {
          date: { $toDate: { $toLong: { $multiply: ["$midNightTimeStamp", 1000] } } },
          unit: "month",
          timezone: "Europe/Zurich"          
        }
      },
      energyConsumed: { $sum: "$energyConsumed" }
    }
  }
])

由于 timezone 选项,它可能比 $dateToString: { format: "%Y-%m" ... 更精确。