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();