MongoDB分组方式
我们用惯了MySQL等关系型数据库的group,一开始用MongoDB的聚合统计有点麻烦,所以在这里做一个本人的使用记录。
分组方式:
- 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}},
});
- 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
- 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一个它的实例,作为格林威治开始时间