MongoDB将时间戳转化为时间格式用作aggregate 的$group条件以及在PHP中的使用

MongoDB分组方式

我们用惯了MySQL等关系型数据库的group,一开始用MongoDB的聚合统计有点麻烦,所以在这里做一个本人的使用记录。

分组方式:

  1. group
  • 特征
    group缺点多多,我理解它是mapreduce的低配版,如返回结果集不能超过16M, group操作不会处理超过10000个唯一键,不支持分片,好像还不能利用索引。
    用法:有以下6个参数

1.key:用来分组文档的字段。和keyf两者必须有一个
2.keyf:可以接受一个javascript函数。用来动态的确定分组文档的字段。和key两者必须有一个
3.initial:reduce中使用变量的初始化
4.$reduce:执行的reduce函数。
5.condition:执行过滤的条件。
6.finallize:在reduce执行完成,结果集返回之前对结果集最终执行的函数。可选的。

  • 实例:
    collection字段:PACKAGE_CREATED(时间戳),ROUTER_STATUS,ROUTER_CREATED
db.test.group(
	{
       key:{ROUTER_STATUS:true},
       initial:{num:0},
       $reduce:function(doc,prev){
            prev.num++
       },
       condition:{ROUTER_STATUS:{$ne:2}},
       
});
  1. aggregate
db.test.aggregate(
   [
     {
       $project: {
           PACKAGE_CREATED:1,
           yearMonthDay: { $dateToString: { format: "%Y/%m/%d", date: {"$add":[new Date(0),{$multiply:["$PACKAGE_CREATED",1000]},28800000] } }},
           time:new Date(0)
        
       },
       $match: {
         
           yearMonthDay: '2019/12/26'       
       }
     }
   ]
)

关键点在于{"$add":[new Date(0),{$multiply:["$PACKAGE_CREATED",1000]},28800000] };
即格林威治开始时间(1970-01-01 00:00:00)+ 存储时间戳 + 时差。

注意:1)MongoDB时间基本单位是ms,所以乘以1000;
2)我的MongoDB是UTC时区,即中时区(0度经线)而中国是东八区,所以加8h

  1. PHP中使用

需要安装MongoDB扩展

<?php
  namespace Test;
  use MongoDB\BSON\UTCDateTime;
  class Test(){
      public function  test()
      {
        $utcdatetime = new UTCDateTime(0);//1970.01.01 00:00:00
        $repair_time = 3600000 * 8;//修复时差
      	$pipeline[] = [
            '$match' => ['PACKAGE_CREATED' => ['$gte'=>$start_time,'$lte' => $end_time]]
        ];
         $pipeline[] = [

            '$project' => [
                'datetime' => ['$dateToString' => [ 'format' => "%Y/%m/%d", 'date' => ['$add' => [$utcdatetime,['$multiply' => ['$ROUTER_DELIVERED',1000]],$repair_time]]]]

            ]
        ];
        $pipeline[] = [
            '$group' => ['_id' => ['router_delivered' => '$datetime'], 'count' => ['$sum' => 1]]
        ];
        $pipeline[] = [
            '$project' => ['_id' => 0,'router_delivered' => '$_id.router_delivered','count' => '$count']
        ];
        $pipeline[] = [
            '$sort' => ['router_delivered' => 1]
        ];
        //要求返回数组结果,而不是BSON对象
        $options = [
            'typeMap' =>  [
                'root' => 'array',
                'document' => 'array',
                'array' => 'array'
            ]
        ];
        $data = $this->db->aggregate($pipeline,$options)->toArray();
        var_dump($data);
	  }
  }

关键是要使用MongoDB扩展的MongoDB\BSON\UTCDateTime类,new一个它的实例,作为格林威治开始时间

参考

  1. MongoDB时间戳转格式化日期
  2. MongoDB时间戳转化日期格式出现少8h的原因?
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章