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的原因?
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章