mongodb 系列(二)使用mongoTemplate的Aggregation类进行分组,分页操作

时间:2025-04-28 07:18:46

mongodb 系列(一) mongodb 数据备份与还原

mongodb 系列(二)使用mongoTemplate的Aggregation类进行分组,分页操作

mongodb 系列(三)Windows下MongoDB安装及创建用户名和密码

mongodb 系列(四)MongoDB常用命令

mongodb 系列(五)MongoDB 学习

1.应用场景

mongodb数据库有一张职位搜索表(t_position_search),里面存储里一些冗余数据(存在一些数据除了id不同其余字段都相同的数据),其中有一个字段是postId,我的需求是在多个相同postId的数据中我只取其中一条(任意一条无所谓,因为相同postId的数据中除了id不同其余字段都相同,我不需要id字段,所以取任意一条无所谓),此时就需要用到mongoTemplate的分组语句。

最终代码

public PageForm queryForPage(QueryForm queryForm,
                             String companyId,
                             Set<String> suitOrgCodeSet,
                             String postKey,
                             String postName,
                             Integer recruitType,
                             String workPlaceCode,
                             String postTypeCode,
                             String orgCode,
                             String siteCode,
                             String salaryCode,
                             String educationCode,
                             Date publishBeginDate) {

    // 构建查询条件
    Criteria criteria = ("companyId").is(companyId);

    // 适用机构列表
    List<Criteria> criterias = new ArrayList<>();
    for(String suitOrgCode:suitOrgCodeSet){
        Criteria newCriteria = ("orgCode").regex(suitOrgCode + "($|/.*)");
        (newCriteria);
    }
    Criteria[] result = (new Criteria[()]);
    (result);

    // 招聘类型
    ("recruitType").is(recruitType);

    // 职位名称(模糊查询)
    if((postName)){
        ("externalPostName").regex(".*" + postName + ".*");
    }
    // 职位关键字(模糊查询)
    if((postKey)){
        ("postKeySearch").regex(".*" + postKey + ".*");
    }
    // 学历
    if((educationCode)){
        ("educationCode").is(educationCode);
    }
    // 工作地点
    if((workPlaceCode)){
        // 数组中元素的具体查询
        //("workPlaceCodeList").elemMatch(new Criteria().in(workPlaceCode));
        // 数组中元素的正则匹配的模糊查询
        ("workPlaceCodeList").elemMatch(new Criteria("$regex").is(workPlaceCode + "($|/.*)"));
    }
    // 职位类型(匹配当前职位类型及其以下职位类型)
    if((postTypeCode)){
        ("postTypeCode").regex(postTypeCode + "($|/.*)");
    }
    // 所属机构(匹配当前机构及其以下机构)
    if((orgCode)){
        ("orgCode").regex(orgCode + "($|/.*)");
    }
    // 站点
    if((siteCode)){
        ("siteCodeList").elemMatch(new Criteria().in(siteCode));
    }
    // 薪酬范围
    if((salaryCode)){
        ("salaryCode").is(salaryCode);
    }
    // 发布时间:终止日期为当前时间
    if(publishBeginDate != null){
       (("publishFirstDate").gte(publishBeginDate),      ("publishFirstDate").lt(new Date()));
    }


    // 分组查询数据
    Aggregation aggregation = (
            (criteria),            //查询条件
            ("postId")             //分组条件
                       .first("postId").as("postId")
                       .first("top").as("top")
                       .first("publishFirstDate").as("publishFirstDate")
                       .first("orgCode").as("orgCode"),
            (new Sort(,"publishFirstDate"))  // 排序
                       .and(new Sort(,"publishFirstDate")),
            ((() - 1) * ()),//跳到第几个开始
            (())//查出多少个数据
    );
    AggregationResults<PositionSearchPo> results = 
    (aggregation,"t_position_search", );
    List<PositionSearchPo> list = ();


    // 分组查询分组后的总记录数
    Aggregation aggregation2 = (
            (criteria),     //查询条件
            ("postId")      //分组条件
    );
    AggregationResults<PositionSearchPo> results2 = 
    (aggregation2,"t_position_search", );
    int dataCount = ().size();

    PageForm pageForm = new PageForm();
    (());
    (());
    (dataCount);
    (list);

    return pageForm;
}

3.分析分组查询

// 分组查询数据
Aggregation aggregation = (
        (criteria),     //查询条件
        ("postId")      //分组条件
                   .first("postId").as("postId")
                   .first("top").as("top")
                   .first("publishFirstDate").as("publishFirstDate")
                   .first("orgCode").as("orgCode"),
        (new Sort(,"top"))  // 排序
                   .and(new Sort(,"publishFirstDate")),
        ((() - 1) * ()),//跳到第几个开始
        (())//查出多少个数据
);
AggregationResults<PositionSearchPo> results = (aggregation,"t_position_search", );
List<PositionSearchPo> list = ();

(criteria)  是添加查询条件。

("postId")  是添加分组字段。后面的 first("postId").as("postId") 代表需要查询的字段映射到实体里的名称,

因为我需要查出这些字段,且后面的排序也需要这些字段,所以必须映射出来,否则如果不添加这些映射,使用group方法,查询出来的实体类中的字段只有postId字段,而且postId的值还被映射到实体中的id字段上去了。也就是说,如果没有后面的first方法,查询出来的实体里面只有id有值,而且这个id的值也不是数据库中id的值,而是postId的值,其余的字段都是没有值的,而且后面添加的排序方法也会报错,因为根本没有查询出来top和publishFirstDate字段。所以可以把需要查询的字段,以first的方式映射出来。

我搜了一下方法,这个方法是查询出指定字段,但是我尝试和group方法一起用的时候,根本不能查询出除了id以外其他的字段,所以根本就没有用,也可能是我没找到对的使用方法,所以我只能放弃使用project方法了。

 还有,如果没有group分组,当然也可以不使用project方法,查询出来的实体包含所有的字段信息,所以我猜想这个group方法里默认查出的字段只有分组的这个字段。

(new Sort(,"top")) .and(new Sort(,"publishFirstDate")),这是根据多个字段进行排序。

因为要查询出总的数据条数,所以重复查询了两次,第一次是根据页码查询出当前页的数据,第二次是查询出总的数据条数

4.分析mogodbTemplate别的查询语句

如果查询条件中有集合,而且是或的关系

// 适用机构列表
List<Criteria> criterias = new ArrayList<>();
for(String suitOrgCode:suitOrgCodeSet){
    Criteria newCriteria = ("orgCode").regex(suitOrgCode + "($|/.*)");
    (newCriteria);
}
Criteria[] result = (new Criteria[()]);
(result);

如果数据库中的记录中,某一个字段是数组,查询条件中数值精准匹配到这个数组中的其中一个元素

// 工作地点
if((workPlaceCode)){
    // 数组中元素的具体查询
    ("workPlaceCodeList").elemMatch(new Criteria().in(workPlaceCode));
}

如果数据库中的记录中,某一个字段是数组,查询条件中数值模糊匹配到这个数组中的其中一个元素

// 工作地点
if((workPlaceCode)){
    // 数组中元素的正则匹配的模糊查询
    ("workPlaceCodeList").elemMatch(new Criteria("$regex").is(workPlaceCode + "($|/.*)"));
}

范围查询

// 发布时间:终止日期为当前时间
if(publishBeginDate != null){
   (("publishFirstDate").gte(publishBeginDate), ("publishFirstDate").lt(new Date()));
}

gte是大于或等于,gt是大于,lte是小于或等于,lt是小于