Mgo庫的常見坑總結
來自: http://ipfans.github.io/2016/01/something-about-mgo-driver/
mgo庫 是一個很好用的 MongoDB 驅動。對我們來說,主力數據庫是 MongoDB ,因此這個驅動對我們來說也是非常重要的。但是,mgo庫有些問題算是一些坑,這里我做了一些簡單的整理。
一些關于bson.ObjectId的問題
ObjectId為空的判斷
如果你看 bson.ObjectId 定義的話,它是一個 string 類型的數據。但是如果你直接定義一個結構,并且生成對象時,這個對象并不是這樣的。
我們首先定義一個結構體:
type Home struct {
ID bson.ObjectId `bson:"_id,omitempty"`
Name string `bson:"name"`
}
然后看看一個生成的內容
h := Home{Name: "123"}
fmt.Println(h.ID)
結果是 ObjectIdHex("") 。換句話說,如果你是想判斷一個結構體的 ObjectId 是否為空,使用 h.ID == "" 是一定會結果為 false 的。如果你想判斷是否為空,正確的方式應該為:
h := Home{Name: "123"}
fmt.Println(h.ID)
fmt.Println(h.ID.Hex() == "")
正確的生成ObjectId
首先值得注意的是 NewObjectIdWithTime(t time.Time) 這個方法生成的 ObjectId 并不是唯一的,結果可能導致的是插入失敗。最有效的方式是設定 ObjectId 對象支持 omitempty 屬性,就像我上面生成的結構體一樣,由數據庫統一調配生成ObjectId。如果真的確實需要,可以選擇 NewObjctId() 。
時間問題
之前看到有人問,為什么保存的時間進入到數據庫中慢了8個小時呢?原因是在保存進入 MongoDB 時,數據是按照 UTC 時間(不懂什么是UTC? 看這里 )進行的保存,但是取出是按照當前時區來取出。那么問題來了,我的客戶如果不都是國人,我怎么保存時間呢?目前我們采用了兩種方式來確定數據庫的保存時間。一種是 Unix時間戳 ,這個是不受到時區的影響的,由前端格式化為對應的時區時間;另外一種則是需要在額外的對從 MongoDB 數據庫中取出的數據進行額外的時區校準,簡單來說可以這樣:
type Home struct {
ID bson.ObjectId bson:"_id,omitempty"
Name string bson:"name"
InsertTime time.Time bson:"insert_time"
}
func main() {
sess, := mgo.Dial("127.0.0.1")
c := sess.DB("test").C("home")
h := Home{Name: "123", InsertTime: time.Now()}
c.Upsert(bson.M{"name": "123"}, h)
c.Find(bson.M{"name": "123"}).One(&h)
fmt.Println(h.InsertTime.Format("2006-01-02 15:04:05"))
tz, := time.LoadLocation("America/New_York")
fmt.Println(h.InsertTime.In(tz).Format("2006-01-02 15:04:05"))
}</code></pre>
更高效的使用Session
在 MongoDB 中合理使用 Session 可以更高效的操作數據庫,做法是在之前進行一次 Copy 操作:
sessionCopy := mongoSession.Copy()
defer sessionCopy.Close()
collection := sessionCopy.DB(TestDatabase).C("buoy_stations")
log.Printf("RunQuery : %d : Executing\n", query)
// Retrieve the list of stations.
var buoyStations []BuoyStation
err := collection.Find(nil).All(&buoyStations)
if err != nil {
log.Printf("RunQuery : ERROR : %s\n", err)
return
}
log.Printf("RunQuery : %d : Count[%d]\n", query, len(buoyStations))</code></pre>
另外值得一提的是MongoDB本身,目前我們已經提升到了 MongoDB 3.0+ 版本,優勢是相對之前版本的 WiredTiger 引擎比較令人印象深刻(如果有條件可以選擇最新的3.2版本)。大家對之前 MongoDB 中索引建立的痛苦有印象,這個現象在 WiredTiger 引擎中也有所改進。更多的改進可以在 WiredTiger 的 官網 和MongoDB的 性能白皮書 中了解更多。最后,當然,我仍然不建議在非嚴重必要情況下創建多余索引,這對 MongoDB 的性能和資源消耗都有較大影響。
</code></code></code></code></div>