Map-Reduce 是 mongodb 處理批量數據的大殺器,凡是數據量大而且定時處理能知足需求的,均可以試着扔給 mongodb,讓它去 Map-Reduce。golang
如下截取自文檔的圖,能夠清楚的說明 Map-Reduce 的執行過程。先看圖:mongodb
回答問題,Map-Reduce 的執行過程是先 map
而後 reduce
麼?數組
是?恭喜入坑!並且是本身挖坑本身填。仔細再看一遍上文的圖,看到那個灰色的箭頭了?不是每次 map
都有 reduce
的!session
若是 map
的結果不是數組,mongodb 就不會執行 reduce
。很合理的處理邏輯。測試
而後,只有入過坑才能意識到本身挖的坑:對於 map
到的數據,若是在 reduce
時但願作統一的處理,必定會發現數據結果是不完整的。設計
mgo 是 golang 的 mongodb driver。code
首先,構建測試程序。blog
package main import ( "log" "time" "gopkg.in/mgo.v2" . "gopkg.in/mgo.v2/bson" ) type TestTime struct { Id ObjectId "_id" CreationTime time.Time } func main() { session, err := mgo.Dial("127.0.0.1") if err != nil { log.Fatalln("Fatal error:", err.Error()) } defer session.LogoutAll() defer session.Close() tc := session.DB("test").C("testtime") t := time.Now() id := NewObjectId() test := TestTime{ Id: id, CreationTime: t, } tc.Insert(test) var testTime TestTime tc.FindId(id).One(&testTime) log.Println(t) log.Println(t == testTime.CreationTime) }
執行測試程序,查看 mongodb 數據索引
/* 0 */ { "_id" : ObjectId("548d0b3194e33700f5ffaba9"), "creationtime" : ISODate("2014-12-14T03:59:45.123Z") }
時間已是 UTC 了,沒有必要 time.Now().UTC()
,固然,執行下 .UTC()
代碼看起來更明確,也耗費不了多少 CPU,由於,.UTC()
僅僅是賦值時間的 location,其源碼以下:文檔
func (t Time) UTC() Time{ t.loc = UTC return t }
mgo 直接以 time.Time
類型插入 mongodb 的時間精度與 time.Now()
的時間精度是不一樣的:
ms
time.Now()
精度爲 ns
,2014-12-14 11:59:45.123670247 +0800 CST
因此,上文 log.Println(t == testTime.CreationTime)
打印結果是 false
_id
是 mongodb 每一個文檔必備字段,並且是默認索引,就是說無論你用不用,它都會創建索引並佔用存儲空間。
在設計存儲結構時,只要能保證惟一性,便可將其做爲 _id
,例如:
{ "_id" : { "nickname" : "busyStone", "index" : 1 }, "creationtime" : ISODate("2014-11-09T02:00:44.496Z") }
mongodb 是支持組合索引的,那麼,_id.nickname
是否是也能夠做爲索引用呢?
在選中的 collection 上執行 .find({"id.nickname":"busyStone"}).explain()
,nscanned
字段並非預想中的 1,由於,創建的索引是這樣的:
{ "_id" : 1 }
因此,老老實實本身個建索引吧。