mongoose聚合——$group

$group:将集合中的文档分组

数据表

//Students
[{"_id":"60adff66e57f4255b4c7e19a", "name":"唐戚", "student_id":232323, "class_oid":"60adff65e57f4255b4c7e194", "come_year":"2020-01-01T00:00:00.000Z", "grade":{"math":37,"chinese":98,"english":71}, "__v":0 } .....省略16条 {"_id":"60ae02937e294b5894229d70", "name":"安俞", "student_id":232328, "class_oid":"60adff65e57f4255b4c7e199", "come_year":"2021-01-01T00:00:00.000Z", "grade":{"math":29,"chinese":39,"english":79}, "__v":0 }]

代码

示例中只给出aggregate中的参数,文末给出完整代码

1.通过某个字段分组

这里使用come_year分组,数据中有两个年份,2020和2021,$group是通过_id来分组。

聚合参数:

 const query=[
    {
      $group:{
        _id:'$come_year'
      }
    }
  ]

结果:

[
  { _id: 2020-01-01T00:00:00.000Z },
  { _id: 2021-01-01T00:00:00.000Z }
]

 

2.数学运算

找出在2020年和2021年入学学生中各科成绩最高分,最低分,平均分
使用:$max:该分组中最大值
$min:该分组中最小值
$avg:该分组的平均值
$sum:计算总和,$sum:1表示返回总和的1倍
const query=[
    {
      $group:{
        _id:'$come_year',
        maxEnglish:{$max:'$grade.english'},
        minEnglish:{$min:'$grade.english'},
        avgEnglish:{$avg:'$grade.english'},
        total:{$sum:1}
      }
    }
  ]

结果:

[
  {
    _id: 2020-01-01T00:00:00.000Z,
    maxEnglish: 74,
    minEnglish: 5,
    avgEnglish: 42.25,
    total: 12
  },
  {
    _id: 2021-01-01T00:00:00.000Z,
    maxEnglish: 84,
    minEnglish: 39,
    avgEnglish: 63.666666666666664,
    total: 6
  }
]

 

3.在分组中插入字段

获得不同学年有哪些学生,给出姓名

使用$addToSet:在结果文档中插入一个数组

const query=[
    {
      $group:{
        _id:'$come_year',
        test:{$addToSet:'$name'}
      }
    }
  ]

 

结果:

[
  {
    _id: 2020-01-01T00:00:00.000Z,
    test: [
      '凤殷', '吴于', '韩马',
      '尤郝', '喻蒋', '曹罗',
      '钱许', '唐戚', '卜严',
      '谢柳', '薛金', '俞彭'
    ]
  },
  {
    _id: 2021-01-01T00:00:00.000Z,
    test: [ '花唐', '酆史', '朱吴', '平殷', '安俞', '邹尤' ]
  }
]

 

4.计算文档总数

计算有多少学生

可以将_id设为null,就不分组

const query=[
    {
      $group:{
        _id:null,
        total:{$sum:1}
      }
    }
  ]

 

结果:

[ { _id: null, total: 18 } ]

 

5.插入新增字段

获取不同学年学生信息

使用$push:在结果文档中插入值到数组中,和addToSet不同的是,$push要创建副本

const query=[
    {
      $group:{
        _id:'$come_year',
        students:{
          $push:{
            _id:'$_id',
            name:'$name',
            grade:'$grade'
          }
        }
      }
    }
  ]

 

结果:

[
  {
    _id: 2020-01-01T00:00:00.000Z,
    students: [
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object]
    ]
  },
  {
    _id: 2021-01-01T00:00:00.000Z,
    students: [ [Object], [Object], [Object], [Object], [Object], [Object] ]
  }
]

 

 

 

完整代码

const Articles = require('../../model/articles');
const Users = require('../../model/users');
var Departments=require('../../model/departments');
var Students=require('../../model/students');
var Classes=require('../../model/classes');

//$group:将集合中的文档分组
//语法:{ $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } }

//---------------------------------1-----------------
//按照入学日期分组
/*
[
  { _id: 2020-01-01T00:00:00.000Z },
  { _id: 2021-01-01T00:00:00.000Z }
] */
async function group1(){
  const query=[
    {
      $group:{
        _id:'$come_year'
      }
    }
  ]

  await studentsAggregate([...query])
}


//----------------2----------------
//找出在2020年和2021年入学学生中各科成绩最高分,最低分,平均分
/**
 * [
  {
    _id: 2020-01-01T00:00:00.000Z,
    maxEnglish: 74,
    minEnglish: 5,
    avgEnglish: 42.25,
    total: 12
  },
  {
    _id: 2021-01-01T00:00:00.000Z,
    maxEnglish: 84,
    minEnglish: 39,
    avgEnglish: 63.666666666666664,
    total: 6
  }
]
 */
async function group2(){
  const query=[
    {
      $group:{
        _id:'$come_year',
        maxEnglish:{$max:'$grade.english'},
        minEnglish:{$min:'$grade.english'},
        avgEnglish:{$avg:'$grade.english'},
        total:{$sum:1}
      }
    }
  ]

  await studentsAggregate([...query])
}

//------------------3----------------
//插入数组到分组中
/*
[
  {
    _id: 2020-01-01T00:00:00.000Z,
    test: [
      '凤殷', '吴于', '韩马',
      '尤郝', '喻蒋', '曹罗',
      '钱许', '唐戚', '卜严',
      '谢柳', '薛金', '俞彭'
    ]
  },
  {
    _id: 2021-01-01T00:00:00.000Z,
    test: [ '花唐', '酆史', '朱吴', '平殷', '安俞', '邹尤' ]
  }
]
*/
async function group3(){
  const query=[
    {
      $group:{
        _id:'$come_year',
        test:{$addToSet:'$name'}
      }
    }
  ]

  await studentsAggregate([...query])
}

//---------------4------------
//常用计算总数
//[ { _id: null, total: 18 } ]
async function group4(){
  const query=[
    {
      $group:{
        _id:null,
        total:{$sum:1}
      }
    }
  ]

  await studentsAggregate([...query])
}

//----------------------5---------------
//获取不同学年的学生信息
async function group5(){
  const query=[
    {
      $group:{
        _id:'$come_year',
        students:{
          $push:{
            _id:'$_id',
            name:'$name',
            grade:'$grade'
          }
        }
      }
    }
  ]

  await studentsAggregate([...query])
}


/**
 * articles聚合结果模板
 * @param {Array} query 聚合的参数
 */
 async function studentsAggregate(query) {
  try {
    const result = await Students.aggregate([
      ...query
    ])

    console.log(result);

  } catch (err) {
    console.log((query))
    console.log("聚合失败...", err)
  }
}


function main(){
  group5();
}

main();

 

posted @ 2021-05-26 17:16  ellenxx  阅读(584)  评论(0编辑  收藏  举报