MongoTemplate官方文檔:
一、增刪改查
原生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++; } |