mongodb 系列(二)使用mongoTemplate的Aggregation类进行分组,分页操作_当时明月plus的博客-程序员宅基地_aggregation 分组

技术标签: 数据库  mongodb  

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

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

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

mongodb 系列(四)MongoDB常用命令

mongodb 系列(五)MongoDB 学习

1.应用场景

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

2.Dao最终代码

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 = Criteria.where("companyId").is(companyId);

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

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

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


    // 分组查询数据
    Aggregation aggregation = Aggregation.newAggregation(
            Aggregation.match(criteria),            //查询条件
            Aggregation.group("postId")             //分组条件
                       .first("postId").as("postId")
                       .first("top").as("top")
                       .first("publishFirstDate").as("publishFirstDate")
                       .first("orgCode").as("orgCode"),
            Aggregation.sort(new Sort(Sort.Direction.DESC,"publishFirstDate"))  // 排序
                       .and(new Sort(Sort.Direction.DESC,"publishFirstDate")),
            Aggregation.skip((queryForm.getCurrentPage() - 1) * queryForm.getPageSize()),//跳到第几个开始
            Aggregation.limit(queryForm.getPageSize())//查出多少个数据
    );
    AggregationResults<PositionSearchPo> results = 
    mongoTemplate.aggregate(aggregation,"t_position_search", PositionSearchPo.class);
    List<PositionSearchPo> list = results.getMappedResults();


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

    PageForm pageForm = new PageForm();
    pageForm.setCurrentPage(queryForm.getCurrentPage());
    pageForm.setPageSize(queryForm.getPageSize());
    pageForm.setDataCount(dataCount);
    pageForm.setPageData(list);

    return pageForm;
}

3.分析分组查询

// 分组查询数据
Aggregation aggregation = Aggregation.newAggregation(
        Aggregation.match(criteria),     //查询条件
        Aggregation.group("postId")      //分组条件
                   .first("postId").as("postId")
                   .first("top").as("top")
                   .first("publishFirstDate").as("publishFirstDate")
                   .first("orgCode").as("orgCode"),
        Aggregation.sort(new Sort(Sort.Direction.DESC,"top"))  // 排序
                   .and(new Sort(Sort.Direction.DESC,"publishFirstDate")),
        Aggregation.skip((queryForm.getCurrentPage() - 1) * queryForm.getPageSize()),//跳到第几个开始
        Aggregation.limit(queryForm.getPageSize())//查出多少个数据
);
AggregationResults<PositionSearchPo> results = mongoTemplate.aggregate(aggregation,"t_position_search", PositionSearchPo.class);
List<PositionSearchPo> list = results.getMappedResults();

Aggregation.match(criteria)  是添加查询条件。

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

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

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

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

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

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

4.分析mogodbTemplate别的查询语句

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

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

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

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

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

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

范围查询

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

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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xuruanshun/article/details/100896888

智能推荐

PL/SQL教程(转)_weixin_33829657的博客-程序员宅基地

2019独角兽企业重金招聘Python工程师标准&gt;&gt;&gt; ...

GENERIC_JDBC_CONNECTOR_0016:Can't fetch schema -_GE12的博客-程序员宅基地

启动job任务时报错解决:创建generic-jdbc-connector link 时:Identifier enclose:  注意  这里不能直接回车!要打一个空格符号!因为如果不打,查询mysql表的时候会在表上加上“”,导致查询出错!

如何做一款成功的应用(下)_hengshujiyi的博客-程序员宅基地

”阅读器1 接 如何做一款成功的应用(上) 3. 开发编程 技术方案的选择会影响应用的使用体验,进而会影响应用最后能否取得成功。 本地化开发 “一次开发,多处部署”这一理念对于中小应用并不合适。从一开始,这一理念就被过度神化。不同的操作系统有着不同的UI规范和模式。除了游戏界面外

概率DP&期望杂题_ShɑΙteж的博客-程序员宅基地

1.http://zhengruioi.com/problem/450​/*f[i][j]:前i个人,有j个人正常出局的概率f[i][j]+=f[i-1][j]*P1+f[i-1][j-1]*p2; 留下来/被日死 正常出局 p 别人出局后自己被日死的概率 P2=(1-p)^(j-1);P1=(1-P1)f[i][k]*P2 前K个过后都没有被日死最...

IDEA默认Maven设置_NFE_W的博客-程序员宅基地

IDEA是自带Maven的,但版本有点低,故自己下了新版的Maven,但每次使用创建或者导入Maven项目的时候,IDEA都会使用系统默认的Maven,如下图所示:此时,如果想默认使用自定义安装的Maven,需要点击Maven home directory进行配置。如果在创建时,想使用自动义安装的Maven,可以在File-&amp;gt;Other Settings -&amp;gt;Setting...

linux shell rman删除归档_rman备份与恢复_weixin_39748838的博客-程序员宅基地

1 数据库备份方法1.1数据库备份方法分类1.2 数据库备份方法说明逻辑备份:指通过逻辑导出对数据进行备份,逻辑备份的数据只能基于备份时刻进行数据转储,所以恢复时也只能恢复到备份时保存的数据。对于备份点和故障点之间的数据,逻辑备份也是无能为力的,所以逻辑备份适合那些很少变化的数据表。如果通过逻辑备份进行全库备份,通常需要重建数据库,对于可用性很高的是数据库,这种恢复时间太长,通常不被使用。由于逻辑...

随便推点

在ubuntu 9.04 下安装 ibus 中文输入法_besidemyself的博客-程序员宅基地

首先我们需要加入ubuntu下的一个源deb http://ppa.launchpad.net/ibus-dev/ppa/ubuntu jaunty main  deb-src http://ppa.launchpad.net/ibus-dev/ppa/ubuntu jaunty main加入的方法是:在终端输入如下命令 $ sudo gedit /etc/apt/sour

最优前缀码_sunshine9112的博客-程序员宅基地

问题:给定字符集C= {x1,x2,…,xn}和每个字符的频率f(xi),求关于C的一个最优前缀码。解析构造最优前缀码的贪心算法就是哈夫曼算法实例:{5, 5, 10, 10, 10, 15, 20, 25}算法计算结果分析O(nlogn)频率排序;for 循环 O(n),插入操作 O(logn),算法时间复杂度是 O(nlogn)度 O(nlogn+n)=O(nlogn)github源码地址参考...

nsLookUp.exe 的实现_HOLD ON!的博客-程序员宅基地

LookUp.exe 的实现原创yuprxk 最后发布于2014-05-08 12:09:42 阅读数 543 收藏展开d#include &lt;WinSock2.h&gt;#include &lt;iostream&gt;#pragma comment(lib,"ws2_32.lib")using namespace std;int handle_error(){...

【03】品优购电商项目:04-品优购项目(四)_忘尘 丶莫负的博客-程序员宅基地

1. 品优购项目(四)1). 详情页 detail.html 常用单词名称说明主体de_container面包屑导航crumb_wrap产品介绍product_intro ( introduction介绍)预览包preview_wrap(左侧部分)预览缩略图preview_img预览列表preview_list左按钮arrow_prev右按钮arrow_next小图列表preview_items产品详细信息

JavaScript的sort函数报“缺少数字”错误的原因、分析与疑惑_weixin_30906701的博客-程序员宅基地

  我们知道,js的数组具有一个sort方法,这个sort方法还可以传入一个特定形式的比较函数进行自定义排序,它的用法类似这样:[5,4,9,2,7].sort(function(a,b){return(a-b);});这个特定形式的自定义比较函数,要求有两个参数,通常情况下,函数的内容是两个参数本身或其属性的对比,该函数的返回值必须为负数、0和正数之一。另外sort函数会改变数组,而不是返回一...

transform转换__xw2018的博客-程序员宅基地_transform转换方法

transform转换:对元素实现移动、缩放、旋转、斜切等操作属性:2D转换(1)2d移动:translate(x)|translate(x,y);x:x轴移动的向量长度y:y轴移动的向量长度单方向:translateX(x)、translateY(y)(2)2d缩放:scale(xy)|scale(x,y);x:x轴方向缩放y:y轴方向缩放xy:两个方向缩放一样单...

推荐文章

热门文章

相关标签