轉載請在頁首注明作者與出處
一:分組匯總
1.1:SQL樣例
分組匯總的應用場景非常多,比如查詢每個班級的總分是多少,如果用關系形數據庫,那么sql是這樣子的
SELECT count(1),class from score group by class
得到的結果就是每個班分別的總分是多少,那么在mongodb這種非關系數據庫要怎么做呢?
1.2:數據樣例
假如我們有如下數據若干
{ "_id" : "4fe31003-0ee3-47b8-8a1d-0e9f8561c37e", "systemId" : "test", "bizId" : "test", "channel" : "通道一", "msg" : "你好!", "createTime" : ISODate("2016-10-25T09:17:12.228+0000"), "useTime" : NumberLong(274), "success" : NumberInt(1) }
{
"_id" : "4fe31003-0ee3-47b8-8a1d-0e9f8561c37e", "systemId" : "test", "bizId" : "test", "channel" : "通道二", "msg" : "你好!", "createTime" : ISODate("2016-10-25T09:17:12.228+0000"), "useTime" : NumberLong(274), "success" : NumberInt(1) }
1.3:需求
如上短信的發送記錄,我們可能統計不同短信通道channnel的發送數量。
1.4:mongodb查詢語法
db.shortMessageLog.aggregate([{$group : {_id : "$channel" , num : {$sum : 1}}}]);
這意味着對channel進行分組,並且查詢出來的分組名稱以id的形式顯示出來
查詢結果如下:
{ "_id" : "通道一", "num" : NumberInt(12504) } { "_id" : "通道二", "num" : NumberInt(594) }
1.5:匯總時加入查詢條件
這又是一個新的需求,我們可能只想統計一定時間的內的數量,所以我們需要加入查詢條件。
新的語句如下
db.shortMessageLog.aggregate([{$match:{createTime:{$gte:new Date(2016,9,28)}}},{$group : {_id : "$channel" , num : {$sum : 1}}}]);
這里使用$match來匹配指定時間的數量。
小提示:mongodb的月份是從0開始的,也就是上面參數中的9,其實代碼的是10月份。
我這里匹配時間大於2016-10-28號以后的數據,然后再交給后面的條件去分組。
1.6:使用java代碼的實現
我們這里使用spring data mongo,相比原生的mongo驅動,這個確實要好用很多。
實現的需求就是根據時間來分組統計數量
Aggregation agg = null; Criteria createTime = Criteria.where("createTime"); boolean timeTag = false; if(startTime != null){ createTime.gte(startTime); timeTag = true; } if(endTime != null){ createTime.lte(endTime); timeTag = true; } GroupOperation groupOperation = Aggregation.group("channel").count().as("count"); if(timeTag){ agg = Aggregation.newAggregation(ShortMessageLog.class,Aggregation.match(createTime),groupOperation); }else{ agg = Aggregation.newAggregation(ShortMessageLog.class, groupOperation); } AggregationResults<Map> results = mongoTemplate.aggregate(agg,ShortMessageLog.class,Map.class);
