Mgo庫的常見坑總結

ChrRuffin 8年前發布 | 17K 次閱讀 MongoDB 數據庫 NoSQL數據庫

來自: 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>

 本文由用戶 ChrRuffin 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!