需求
需求是这样的,要统计每一周的各个商品的销售记录,使用 echarts 图表呈现,如下图
说实话,一开始听到这个需求的时候,我是有点慌的,因为 MongoDB 的分组玩的比较少(Mysql 也差不多),又要按照对应的星期来进行分组,这在之前学习 MongoDB 的时候还没接触过,于是就准备写了这篇文章,来记录下我是如何进行分组的
MongoDB 的一些时间操作符
时间操作符(专业术语应该不是这个,后文暂且使用这个来描述),后面会用到的
$dayOfYear: 返回该日期是这一年的第几天。(全年366天)
$dayOfMonth: 返回该日期是这一个月的第几天。(1到31)
$dayOfWeek: 返回的是这个周的星期几。(1:星期日,7:星期六)
$year: 返回该日期的年份部分
$month: 返回该日期的月份部分(between 1 and 12.)
$week: 返回该日期是所在年的第几个星期(between 0 and 53)
$hour: 返回该日期的小时部分
$minute: 返回该日期的分钟部分
$second: 返回该日期的秒部分(以0到59之间的数字形式返回日期的第二部分,但可以是60来计算闰秒。)
$millisecond:返回该日期的毫秒部分(between 0 and 999.)
$dateToString:{ $dateToString: { format: <formatString>, date: <dateExpression> } }
日期分组
关于日期分组的话,我是借鉴了这篇文章,也确实带我解惑了下如何按照日期分组。这里贴下我的代码
let list = await this.goodsModel
.aggregate([
{ $project: { date: { $dateToString: ['$created_at', 0, 10] } } },
{ $group: { _id: '$date', count: { $sum: 1 } } },
{ $project: { date: '$_id', _id: 0, count: 1 } }, // 再使用$project将_id改名为date
{ $sort: { date: -1 } }, // 根据日期倒序
])
.exec();
或者使用时间操作符(更准确一点)
let list = await this.goodsModel
.aggregate([
{
$project: { date: { $dateToString: { format: '%Y-%m-%d', date: '$created_at' } } },
},
{ $group: { _id: '$date', count: { $sum: 1 } } },
{ $project: { date: '$_id', _id: 0, count: 1 } }, // 再使用$project将_id改名为date
{ $sort: { date: -1 } }, // 根据日期倒序
])
.exec();
通过
要注意的是,$group 里的属性必须为_id,不然无法分组
获取到的数据如下(这里只显示一周)
[
{ "count": 54, "date": "2021-08-30" },
{ "count": 29, "date": "2021-08-29" },
{ "count": 16, "date": "2021-08-28" },
{ "count": 17, "date": "2021-08-27" },
{ "count": 12, "date": "2021-08-26" },
{ "count": 6, "date": "2021-08-25" },
{ "count": 0, "date": "2021-08-24" }
]
如果只是日期和总商品的话,上面就足以显示对应的数据了,可我要根据星期进行分组的话,就需要替换 MongoDB 的时间转化函数了
星期分组
星期分组的话,其实也挺简单的,只需要把上面的
$project: { day: { $dateToString: { format: "%Y-%m-%d", date: "$created_at" } } }