MongoDB是以UTC格式來存儲全部時間的,查詢的時候也是返回UTC時間,不提供在數據庫鏈接級別的timezone支持,這就帶來一個問題:沒法使用groupby對日期進行聚合,由於你所在的timezone的日期跟UTC的日期不徹底是同一天。html
雖然這個功能在社區裏面呼聲仍是比較高的,可是10gen公司至今都沒有給出timezone支持的時間表。 https://jira.mongodb.org/browse/SERVER-6310git
這樣對於想要存儲正確時間到mongodb中,有兩種套路。github
1:存入數據庫以前,把datetime轉成UTC時間;從數據庫讀取時(讀取的結果並不帶timezone信息,由於它確定是UTC時間),再把UTC時間轉成local timezone。 具體參照這裏mongodb
2:使用驅動自己提供的tz_aware=True來進行半自動轉,爲何說是半自動,由於插入的時候datetime必須帶有tzinfo信息,它才能幫助你自動轉換成UTC,否則就直接存入mongoDB了。查詢的時候datetime帶了UTC的tzinfo,須要使用astimezone把它轉成local timezone。 具體參照這裏數據庫
對於groupby的問題,到目前尚未好的解決方案,要麼把數據所有拉到客戶端,而後進行統一轉換,再統計。這樣代價會比較大,對於大一點數據來講就不太現實。apache
若是不須要同一數據支持多timezone的話,能夠把本地時間直接存入到mongodb中 ;)app
紀錄一次本身碰到的一個跟groupby相關的具體問題及解決方案。url
《背景》spa
經過各個app server上的td-agent來收集apache的access log,並存入mongoDB中code
td-agent用於收集access log的配置
<source> type tail path /var/log/httpd/access_log pos_file /var/log/td-agent/access_log.pos tag apache.access format /^(?<host>[^ ]*) \[(?<time>[^\]]*)\] (?<user>[^ ]*) (?<url>[^ ]*) (?<code>[^ ]*) (?<size>[^ ]*) (?<taken>[^ ]*)$/ time_format %d/%b/%Y:%H:%M:%S %z </source> <match apache.access> # plugin type type mongo_timezone # timezone utcoffset 8 # mongodb db + collection database apache collection access # mongodb host + port host 127.0.0.1 port 27017 # interval flush_interval 10s </match>
爲了使得groupby能夠對日期聚合,必須把本地時間直接存入mongoDB,全部的hack就在mongo_timezone這個mongo_timezone 本身定製plugin裏面了。(把該定製文件放入/etc/td-agent/plugin/就能夠在配置文件裏面直接使用)
每個fluent的event log包含三部分,tag,time,message。這是一個sample
2013-08-09T00:00:30+09:00 apache.access {"host":"117.136.88.98","user":"1","request":"POST /index/ HTTP/1.1","code":"200","size":"822","taken":"40790"}
根據fluent-plugin-mongo的源代碼,這個timestamp形式的time值默認會寫入mongoDB,能夠在這裏定製我須要的值。
--EOF--