最近需要做个统计,计算一个销售或部门(n 个销售),在一段时间内(n 天)的成交数据
每个销售每天一条记录(si_id 和 date 组合索引),data 数组存放了每个产品的成交数量
简单分析后,我们需要得到的就是 data
下每个 product_id
的 num
之和
在查询出来后,进行循环处理,结果由于数据量太大导致内存溢出。能不能像 MySQL 中直接进行 GROUP BY
+ SUM()
呢?
数据在 Mongo,大致结构如下:
[
'si_id' => 1,//销售ID
'date' => '2019-05-28',//Y-m-d
'data' => [
0 => [
'product_name' => '产品A',
'product_id' => 1,
'num' => 123
],
1 => [
'product_name' => '产品B',
'product_id' => 2,
'num' => 123
],
//more..
],
]
查看文档后发现了 Mongo 的聚合 Aggregation,其中有几种实现方式
这里分享的是管道方式,Map-Reduce和单用途聚合可以查看官方文档
管道模式顾名思义就是像个 pipeline
一样,经过层层筛选,最终得到你想要的结果
第一阶段
首先使用 $match
添加查询条件,把销售 ID 条件和 时间条件写上:
[
'$match' => [
'si_id' => [
'$in' => [1,2,3,4]
],
'date' => [
'$gte' => '2019-05-01',
'$lte' => '2019-05-30'
]
]
]
第二阶段
如果需要,使用 $project
指定查询列,例如我们想分次查,一次求一个产品的和:
[
'$project' => [
'data' => [
'$filter' => [
'input' => '$data',
'as' => 'temp',
'cond' => [
'$eq' => [
'$$temp.product_id', 1 //只查询产品ID为1的记录
]
]
]
]
]
]
由于我们的数据结构特殊,需要处理数组,所以要加上 $unwind
[
'$unwind' => '$data'
]
第三阶段
使用 $group
进行求和,也就是我们需要的结果:
[
'$group' => [
'_id' => '$data.product_id',
'num' => [
'$sum' => '$data.num' //对num字段进行求和
]
]
]
意犹未尽的你可以再去看看文档,是否能进一步优化你的日常开发
步骤 | 作用 | SQL等价运算符 |
---|---|---|
$match | 过滤 | WHERE |
$project | 投影 | AS |
$sort | 排序 | ORDER BY |
$group | 分组 | GROUP BY |
$skip/$limit | 结果限制 | SKIP/LIMIT |
$lookup | 左外连接 | LEFT OUTER JOIN |
see MongoDB\Collection::aggregate()