mongodb中按天進行聚合查詢的例項教程
前言
最近在寫專案的時候遇到一個問題,使用mongodb記錄了用例的執行結果,但是在時間的記錄上使用的是date格式,現在有一個需求,以天為單位,統計一下每天成功的用例和失敗的用例,說到統計,肯定是要用到聚合查詢,但是如果以date格式的時間為group依據,那麼等同於沒有分組,因為在記錄用例的時間幾乎不可能同時,今天查閱了一下相關文件,可以使用mongodb的$dateToString命令來完成這個需求
問題來源
假如我們以如下的資料
/* 1 */ { "_id" : ObjectId("5d24c09651a456efbc231669"),"time" : ISODate("2019-07-08T10:12:35.125Z"),"result" : "Pass" } /* 2 */ { "_id" : ObjectId("5d24c09e51a456efbc23166a"),"time" : ISODate("2019-07-08T10:12:36.125Z"),"result" : "Pass" } ... ... /* 10 */ { "_id" : ObjectId("5d24c0d851a456efbc231672"),"time" : ISODate("2019-07-06T10:10:52.125Z"),"result" : "Pass" } /* 11 */ { "_id" : ObjectId("5d24c0e751a456efbc231673"),"result" : "Fail" }
我的預期結果是
{'_id': '2019-07-06','Pass': 1}
{'_id': '2019-07-06','Fail': 2}
{'_id': '2019-07-07','Pass': 2}
{'_id': '2019-07-07','Fail': 1}
{'_id': '2019-07-08','Pass': 2}
{'_id': '2019-07-08','Fail': 3}
如果按照以前的聚合方式,通過$time來分組,由於每個時間都不相同,所以這樣的聚合就相當於沒有聚合
#coding:utf-8 from pymongo import MongoClient client = MongoClient(host=['%s:%s'%("127.0.0.1",27017)]) G_mongo = client['test'] pipeline = [ {'$group': {'_id': '$time','count': {'$sum': 1}}},] for i in G_mongo['test'].aggregate(pipeline): print(i)
得到的結果
{'_id': datetime.datetime(2019,7,6,10,32,125000),'count': 1}
{'_id': datetime.datetime(2019,8,11,22,52,12,36,35,'count': 1}
可以看到,由於$time上的時間,誰和誰都不一樣,所以如果以$time為分組物件的話每個統計都是1。
問題的解決
在分組的時候有一個$dateToString指令,可以將日期格式的值轉化為字串,比如這裡因為需求是要以天為單位,所以我將其轉為
%Y-%m-%d的字串格式,具體的$grouop如下
{'$group': {'_id': {"$dateToString":{'format':'%Y-%m-%d','date':'$time'}},'count': {'$sum': 1}}}
$dateToString的說明文件可以訪問https://docs.mongodb.com/manual/reference/operator/aggregation/dateToString/ 檢視,簡單介紹一個
{ $dateToString: { date: <dateExpression>,format: <formatString>,timezone: <tzExpression>,onNull: <expression> } }
它需要四個引數,只有date引數是必須的,指定資料來源,format是轉化的格式,timezone為時區,onNull是如果日期值不存在時返回的值。
#coding:utf-8 from pymongo import MongoClient client = MongoClient(host=['%s:%s'%("127.0.0.1",27017)]) G_mongo = client['test'] pipeline = [ # {'$group': {'_id': '$time',{'$group': {'_id': {"$dateToString":{'format':'%Y-%m-%d','count': {'$sum': 1}}} ] for i in G_mongo['test'].aggregate(pipeline): print(i)
上面程式碼執行的結果如下
{'_id': '2019-07-06','count': 2}
{'_id': '2019-07-07','count': 3}
{'_id': '2019-07-08','count': 5}
這個看起來還不錯,但是離我的目標還差一點,因為它還沒有按照用例執行結果進行分組,再以天進行倒序排列
#coding:utf-8 from pymongo import MongoClient client = MongoClient(host=['%s:%s'%("127.0.0.1",{'$group': {'_id': {'date':{"$dateToString":{'format':'%Y-%m-%d','result':'$result'},{'$sort':{"_id.date":-1}} ] for i in G_mongo['test'].aggregate(pipeline): print(i)
得到的結果如下
{'_id': {'date': '2019-07-08','result': 'Fail'},'count': 3}
{'_id': {'date': '2019-07-08','result': 'Pass'},'count': 2}
{'_id': {'date': '2019-07-07','count': 1}
{'_id': {'date': '2019-07-06','count': 2}
檢視文件,除了使用$dateToString指令還可以使用$dayOfMonth指令
pipeline = [ {'$group': {'_id': {'date':{"$dayOfMonth":{'date':'$time'}},{'$sort':{"_id.date":-1}},]
但是這個指令只能適用於單一月份,如果兩個月就會有交集,如7月6號和6月6號的會聚合到一起
上面得到的結果是
{'_id': {'date': 8,'count': 3}
{'_id': {'date': 8,'count': 2}
{'_id': {'date': 7,'count': 1}
{'_id': {'date': 6,'count': 2}
{'_id': {'date': 6,'count': 1}
所以需要根據需求靈活的使用各種指令。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對我們的支援。