关于MongoDB处理统计图数据(按天,小时)

说明:本文基于nest.js,typescript语法,mongoose,moment

前言:在网上找了很长时间,最终总结了如下两种方法,仅供参考

需要导的包:

import * as moment from moment;

import { DateTime } from ts-luxon;

import { InjectModel } from @nestjs/mongoose;

第一种方法:正常循环

//近七天趋势分析
      const water_rush_chart = [];
      for (let i = 0; i < 7; i++) {
        const count = await this.WaterRushModel.aggregate([
          {
            $match: {
              create_time: {
                $gte: DateTime.local().plus({ day: -i }).startOf(day),//前i天的00:00
                $lte: DateTime.local().plus({ day: -i }).endOf(day),//前i天的59:59秒
              },
            },
          },
            //分组
          {
            $group: {
              _id: null,    //根据什么分组
              value: { $sum: $flow },    //求需要的字段值之和,$sum为求和,$flow为字段
              dataDate: { $push: $dataDate },
            },
          },
        ]);

        water_rush_chart.unshift({
          x: DateTime.local()
            .plus({ day: -(i + 1) })
            .toFormat(LL-dd),    //转化为月-日
          y: count[0] ? count[0].value.toFixed(2) : 0,
          s: 数量,
        });
      }

第二种方法:通过分组将数据按照所需时间分组

//近24小时趋势图
      const count1 = await this.studentModel.aggregate([
        {
          $match: {
            created_at: {
              $gte: DateTime.local().plus({ hours: -24 }).startOf(hour),
              $lte: DateTime.local().plus({ hours: -1 }).endOf(hour),
            },
          },
        },
        //分组
        {
          $group: {
            _id: {
              $subtract: [
                { $subtract: [$created_at, new Date(1970-01-01)] },
                {
                  $mod: [{ $subtract: [$created_at, new Date(1970-01-01)] }, 1000 * 60 * 60 /*聚合时间段,24小时*/],
                },
              ],
            },
            name: { $push: $pump_room_name },
            score: { $avg: $score },
            time: { $push: $created_at },
          },
        },
        //排序
        {
          $sort: {
            time: 1,
          },
        },
      ]);

      //数据库查到的数据先存入数组
      const student_arr = [];
      count1.filter((item) => {
        //添加平均成绩
        student_arr.unshift({
          x: moment(item.time[0]).format(HH:00),
          y: item.score || 0,
          s: 平均成绩,
        });
      });

      //学生平均成绩趋势如(不包含当前小时)
      const studnet_chart = [];
      let num1 = 0;
      for (let i = 0; i < 24; i++) {
        //获取当前时间
        const time = DateTime.local()
          .plus({ hour: -(i + 1) })
          .startOf(hour)
          .toFormat(HH:00);
        //判断所处时间是否有数据
        if (num1 < student_arr.length && student_arr[num1].x === time) {
          student_chart.unshift(student_arr[num1]);
          num1++;
        } else {
          //为了防止数据库数据不全,数据库中没有的默认0
          student_chart.unshift({
            x: time,
            y: 0,
            s: 平均成绩,
          });
        }
      }

两种方法各有优势,具体根据定时任务存储的时间而定.

语法方面也可进行优化,这里不做过多叙述.

如有更好的方法欢迎留言.

这里再分享几篇参考的文章以及感觉比较全面的MongoDB总结:

管道相关方法:

经验分享 程序员 微信小程序 职场和发展