【MongoDB】--MongoDB聚合Aggregation

目录

一、前言

聚合操作组值来自多个文档,可以对分组数据执行各种操作以返回单个结果。聚合操作包含三类:单一作用聚合、聚合管道、MapReduce

  • 单一作用聚合:提供对常见聚合过程的简单访问,操作都从单个集合聚合文档
  • 聚合管道操作:将文档在一个管道处理完毕后,把处理的结果传递给下一个管道进行再次处理
  • MapReduce操作:是将集合中的批量文档进行分解处理,然后将处理后的各个结果进行合并输出

二、聚合管道操作

管道的主要函数方法如下:

java 复制代码
名称	                描述	                  类比sql
$avg	      计算均值	   avg
$first	  返回每组第一个文档,如果有排序,按照排序,如果没有按照默认的存储的顺序返回第一个文档。 	  limit 0,1
$last	返回每组最后一个文档,如果有排序,按照排序,如果没有按照默认的存储的顺序返回最后一个文档。	 -
$max	根据分组,获取集合中所有文档对应值的最大值。	 max
$min	根据分组,获取集合中所有文档对应值的最小值。	 min
$push	将指定的表达式的值添加到一个数组中。	 -
$addToSet	将表达式的值添加到一个集合中(无重复值,无序)。	-
$sum	计算总和	 sum
$stdDevPop	返回输入值的总体标准偏差(population standard deviation)	-
$stdDevSamp	返回输入值的样本标准偏差(the sample standard deviation)	-

2.1、实际案例1

classDo是班级信息

StudentDo是学生信息

teacherDo是老师信息

复制代码
 一个学生 关联一个班级;一个班级有多个学生;
 一个老师挂在多个班级下;一个班级拥有多个老师;

主要表结构字段:

java 复制代码
ClassDo班级信息
   @JSONField(name = "class_no")
    private String classNo;
    @JSONField(name = "class_name")
    private String className;
    @JSONField(name = "class_position")
    private String classPosition;
 
    List<StudentDo> studentDos; //关联学生们
    List<TeacherDo> teacherDos; //关联老师们

StudentDo学生信息
   @JSONField(name = "stu_id")
    private String stuId;
    @JSONField(name = "stu_name")
    private String stuName;
    @JSONField(name = "stu_age")
    private String stuAge;
    @JSONField(name = "chinese_score")
    private String chineseScore;
    @JSONField(name = "match_score")
    private String matchScore;
    @JSONField(name = "class_id")
    private ObjectId classId; //学生属于哪个班级
    
    ClassDo classDo; //学生属于具体哪个班

TeacherDo老师信息
    @JSONField(name = "te_id")
    private String teId;
    @JSONField(name = "te_name")
    private String teName;
    @JSONField(name = "te_age")
    private String teAge;
    @JSONField(name = "class_ids")
    private List<ObjectId> classIds; //老师教学多个班级
   

(1)、案例--根据学生no,找到对应班级名称

java 复制代码
    public void aggregateStudent(String stuName,String stuAge){
        int page =2,maxElements=10;
        Criteria criteria = new Criteria();
        criteria.and("stuName").is(stuName);
        criteria.and("stuAge").is(stuAge);
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.lookup("w_class","classId","_id","classDo"),
//                Aggregation.unwind("classDo") //加上这行,那么classDo关联时,classDo节点为null,那么就去去掉这一行
                Aggregation.unwind("classDo",true), //classDo为null,这个数组[index]还存在,但classDo字段不存在了
                //  计算思路:skip((页码-1)* maxElements)
                Aggregation.sort(Sort.by("stu_age").descending()),
                Aggregation.skip((page-1)*maxElements),
                //  利用limit:限制输出的文档数,即需展示的数据量(可理解为每页显示的数量)
                Aggregation.limit(maxElements)
        );
        /**
         * aggregate()表明 主要查询w_student表,对应的查询条件是match(criteria);
         * 接着要关联w_class表。  w_student表的class_id字段关联w_class表的_id字段。
         */
        AggregationResults<JSONObject> aggregationResults = mongoTemplate.aggregate(aggregation, "w_student", JSONObject.class);
        List<JSONObject> infoList = aggregationResults.getMappedResults();
        log.info("aggregationResults:{}", JSON.toJSONString(infoList));

    }

(2)、案例--这个班级有哪些学生和哪些老师在任课

备注:主表有查询条件;关联两个子表;以主表返回结果

java 复制代码
  public void aggregateClass(String className){
        Criteria criteria = new Criteria();
        criteria.and("className").is(className);
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.lookup("w_student","_id","classId","studentDos"),
                Aggregation.lookup("w_teacher","_id","classIds","teacherDos")
        );
        AggregationResults<JSONObject> aggregationResults = mongoTemplate.aggregate(aggregation, "w_class", JSONObject.class);
        List<JSONObject> infoList = aggregationResults.getMappedResults();
        log.info("aggregationResults:{}", JSON.toJSONString(infoList));

    }

2.2、实际案例2

现有两个mongodb表,business_permission存储某个业务的权限信息;business_a表是具体某个业务;其中business_a表的主键id关联到business_permission表的business_id。

(1)、案例--主表和关联表都有条件限制,且分页返回

由于这里的查询要求分页,那么只能对要分页的主表进行返回。

java 复制代码
  public Object templateAggregation2(int page,int size){
         //主表的查询条件
        Criteria criteria = new Criteria();
        criteria.and("state").is(Boolean.TRUE);
        //关联表的查询条件
        Criteria permissionCri = new Criteria();
        permissionCri.and("templateInfo.business_type").is(7); 

        //
        /**
        templateInfo是关联的表结构;这个结构的permission节点是一个数组,在具体按照要求进行过滤得到需要的权限是否存在
        */
        Criteria businessCriteria = new Criteria();  businessCriteria.andOperator(Criteria.where("templateInfo.permission.id").is("04"),Criteria.where("templateInfo.permission.permission_type").is(2));
        Criteria businessCriteria2 = new Criteria();
businessCriteria2.andOperator(Criteria.where("templateInfo.permission.id").is("01"),Criteria.where("templateInfo.permission.permission_type").is(2));
        List<Criteria> busCriteriaList = new ArrayList<>();
        busCriteriaList.add(businessCriteria);
        busCriteriaList.add(businessCriteria2);
        busCriteriaList.add(Criteria.where("templateInfo.all_flag").is(Boolean.TRUE));
        busCriteriaList.add(Criteria.where("templateInfo.permission").is(null));
        busCriteriaList.add(Criteria.where("templateInfo.permission").is(new ArrayList<>()));
        Criteria[] criArray = new Criteria[busCriteriaList.size()];
        busCriteriaList.toArray(criArray);
        permissionCri.orOperator(criArray);

        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(criteria), //主mongodb自身查询条件
                Aggregation.lookup("business_permission","_id","business_id","templateInfo"), //business_permission的business_id对应主表的id
                Aggregation.match(permissionCri), //关联表查询条件
                Aggregation.sort(new Sort(Sort.Direction.DESC, "update_time")),
                 //  计算思路:skip((页码-1)* maxElements)
                 Aggregation.skip((page-1)*size),
                 Aggregation.limit(size)  //这分页的
              //  Aggregation.group("template_type") //按照分组返回特定的字段值 【可以统计数量】
             //   .sum("id").as("sumValue")  //对id进行求和 
             //   .first("template_code").as("templateCode")
             //   .avg("doc_view_number").as("avgValue")
        );

        AggregationResults<JSONObject> aggregationResults = mongoTemplate.aggregate(aggregation, "business_a", JSONObject.class);
        List<JSONObject> templateList = aggregationResults.getMappedResults();
        log.info("templateList All:{}", JSON.toJSONString(templateList));
        return templateList;
    }
相关推荐
知识分享小能手7 小时前
MongoDB入门学习教程,从入门到精通,MongoDB的选择片键 - 完整知识点(16)
数据库·学习·mongodb
知识分享小能手7 小时前
MongoDB入门学习教程,从入门到精通,MongoDB分片配置完全指南(15)
数据库·学习·mongodb
fLDiSQV1W14 小时前
【MongoDB】MongoDB 概述
数据库·mongodb
知识分享小能手2 天前
MongoDB入门学习教程,从入门到精通,MongoDB的分片简介(14)
数据库·学习·mongodb
希望永不加班2 天前
SpringBoot 整合 MongoDB
java·spring boot·后端·mongodb·spring
sR916Mecz2 天前
MongoDB 详解、应用场景及案例分析(AI)
数据库·mongodb
吴声子夜歌3 天前
Node.js——操作MongoDB
数据库·mongodb·node.js
爬山算法3 天前
MongoDB(80)如何在MongoDB中使用多文档事务?
数据库·python·mongodb
爬山算法3 天前
MongoDB(79)事务的特性是什么?
数据库·python·mongodb
知识分享小能手4 天前
MongoDB入门学习教程,从入门到精通,MongoDB 副本集管理完全指南(13)
数据库·学习·mongodb