【MongoDB】--MongoDB Aggregation

I. Introduction

Aggregation operations group values ​​from multiple documents and can perform various operations on the grouped data to return a single result. Aggregation operations include three categories: single-action aggregation, aggregation pipeline, and MapReduce .

  • Single-role aggregation : Provides simple access to common aggregation procedures that aggregate documents from a single collection
  • Aggregation pipeline operation : After the document is processed in one pipeline, the processing results are passed to the next pipeline for processing again.
  • MapReduce operation : decomposes the batch documents in the collection, and then merges and outputs the processed results.

2. Aggregation pipeline operation

The main function methods of the pipeline are as follows:

名称	                描述	                  类比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. Actual case 1

classDo is class information
StudentDo is student information
teacherDo is teacher information

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

Main table structure fields:

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) Case – Find the corresponding class name based on student no.

    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) Case – which students and teachers are teaching in this class

Note: The main table has query conditions; associate two sub-tables; return results in the main table

  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. Actual case 2

There are two mongodb tables. Business_permission stores the permission information of a certain business; the business_a table is a specific business; the primary key id of the business_a table is associated with the business_id of the business_permission table.

(1). Case – both the main table and the related table have conditional restrictions and are returned in pages.

Since the query here requires paging, only the main table to be paginated can be returned.

  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;
    }

Guess you like

Origin blog.csdn.net/xunmengyou1990/article/details/132006643