mongoTemplate工作中常用方式

MongoTemplate官方文档:

https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo.aggregation.supported-aggregation-operations

   

一、增删改查

原生mongo:

   

Query对象

1、 创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)

2 、精准条件:criteria.and("key").is("条件") 模糊条件:criteria.and("key").regex("条件")

3、封装条件:query.addCriteria(criteria)

4、大于(创建新的criteria):Criteria gt = Criteria.where("key").gt("条件") 小于(创建新的criteria):Criteria lt = Criteria.where("key").lt("条件") 5、Query.addCriteria(new Criteria().andOperator(gt,lt));

6、一个query中只能有一个andOperator()。其参数也可以是Criteria数组。

7、排序 :query.with(new Sort(Sort.Direction.ASC, "age"). and(new Sort(Sort.Direction.DESC, "date")))

   

二、mongoTemplate分组排序、复杂操作

   

分组方法

理解难度

性能对比

是否提倡

mongoTemplate.group();

对比来将这个简单点

70w数据需要2分30秒

在springBoot新的集成环境下,mongoDB已经淘汰该方法了

mongoTemplate.aggregation();

理解之后特别好用

同环境下只需10秒不到

使用中

   

1、mongoTemplate.group(); 分组但并不能使用排序

//封装具体的筛选条件

    Criteria criteria = new Criteria() ;

    criteria.andOperator(

          

        // 筛选大于 getMsgTime > startTime 和 getMsgTime < endTime 的数据 (getMsgTime)

        Criteria.where("getMsgTime").gte(startTime),

        Criteria.where("getMsgTime").lte(endTime));

   

    //mongoDB按"deviceCode"分组 ,这里会默认保留分组字段

    GroupBy groupBy = GroupBy.key("deviceCode")

          

        //新增保留字段 并初始化

        .initialDocument("{ count: 0 , onlineCount: 0 , lastTime: 0}")

          

        //对分组后的数据进行运算 doc代表当前文档,prev代表结果文档 func里面可以使用js语法

        .reduceFunction("function(doc, prev) { prev.count++ ; if(doc.ctlStatus == 1){prev.onlineCount += 1 ;prev.lastTime = doc.getMsgTime ; }}");

   

    GroupByResults<DeviceGroupByResult> results =

          

        //criteria: 筛选条件 , CTL_HEART_BEAT:集合名称/表名 ,DeviceGroupByResult.class:接收数据对象

        mongoTemplate.group(criteria,"CTL_HEART_BEAT",groupBy, DeviceGroupByResult.class);

   

/**这里的接收数据 对象 指的是 将 保留字段 封装成一个对象,并添加get/set方法

* 这里 DeviceGroupByResult.class 类中就包含 deviceCode、count、onlineCount、lastTime 这些属性。

*/

    //对结果集进行处理 这里只能拿到iterator对象,在我看来itertator并没有List集合 香

     Iterator<DeviceGroupByResult> iterator = results.iterator();

       while (iterator.hasNext()){

           //看了下源码这个地方 result.iterator 返回的就是就是结果集 但是只能用迭代器读取

           DeviceGroupByResult deviceGroupByResult = iterator.next();

           }

       }

   

2、mongoTemplate.aggregation(); 分组并排序

//封装具体的筛选条件

Criteria criteria = new Criteria() ;

        criteria.andOperator(

                // 筛选大于 getMsgTime > startTime 和 getMsgTime < endTime 的数据 (getMsgTime)

                Criteria.where("getMsgTime").gte(startTime),

                Criteria.where("getMsgTime").lte(endTime));

   

        //mogoDB按device_code分组查询  

        Aggregation aggregation = Aggregation.newAggregation(

                Aggregation.match(criteria),//添加筛选方法

                Aggregation.group("deviceCode").first("deviceCode").as("deviceCode") //利用deviceCode分组并保留该字段

                        .last("getMsgTime").as("lastTime")//取最后时间作为保留

                        .count().as("count")//统计分个数

                    //这里的ctlStatus在mongoDB里面是以字符串存储,而我想统计它们之和,但是字符串不能直接相加sum(),所以只能先存到List中

                        .push("ctlStatus").as("currentCtlStatusList")

                        .push("getMsgTime").as("cuurentCtlGetTimeList")//这里之所以把时间也push上去,是因为我要取ctlstatus=1时候的时间

              

            //这里排序放在分组后面,所以指定的字段只能是lastTime,而放在分组前面就需要指定getMsgTime数据库字段

            //而且使用sort要注意,sort我发现在70w数据面前 就歇菜了 ,而且回报错

            Aggregation.sort(Sort.by(Sort.Order.asc("lastTime")))

                );

        //aggegation:所有条件的封装 , CTL_HEART_BEAT:集合/表 ,DeviceGroupByResult.class:接收数据对象

        AggregationResults<DeviceGroupByResult> deviceGroupByResults =

            mongoTemplate.aggregate(aggregation, "CTL_HEART_BEAT", DeviceGroupByResult.class);

          

        //这里就很友好了

        List<DeviceGroupByResult> list = deviceGroupByResults.getMappedResults() ;

   

3、循环查询(可能你会遇见需要你循环几次的操作)

Criteria criteria = new Criteria();

//timeFrames  时间集合

for (String time : timeFrames) {

                    //将筛选条件封装到agregaton

                    Aggregation aggregation = Aggregation.newAggregation(

                            //注意这里使用的是 new criteria.adddOperator(criteria) 每次循环都带一个全新的Criteria条件

                            //按照正常逻辑 是不需要在外面 包一层,但是如你这样做了

                            //循环第一遍没问题,第二遍嘿嘿  会提示  对一个参数做了多次筛选,所以这里做了一个隐式传参

                            Aggregation.match(new Criteria().andOperator(criteria.where("STATISTICS_YEAR").is(time), criteria)),

                            Aggregation.group("STATISTICS_TIME").first("STATISTICS_TIME").as("time").sum("CAR_FLOW").as("count"),

                            Aggregation.sort(Sort.by(Sort.Order.asc("time")))

                    );

                    AggregationResults<CarFlowResultVO> carFlowResultVOs = mongoTemplate.aggregate(aggregation, tableName, CarFlowResultVO.class);

                    carFlowResultVOList = carFlowResultVOs.getMappedResults();

   

                    carFlowResultVOMap.put(String.valueOf(count), carFlowResultVOList);

   

                    carFlowResultVOList = new ArrayList<>();

                    count++;

                }

posted @ 2020-11-11 11:27  黑质白章  阅读(2027)  评论(1编辑  收藏  举报