1. 程式人生 > 資料庫 >mongodb中按天進行聚合查詢的例項教程

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}

所以需要根據需求靈活的使用各種指令。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對我們的支援。