mgo初步接觸
Intro
mgo
是mongodb
的go語言繫結,第一次在靜態型別語言中使用ORM,故留個筆記。
模型
mongodb
是schema-less
無模式的NoSQL
非關係型資料庫,理論上來說,在同一個表(mongodb
中稱為collection
)中的行(mongodb
稱為document
)也可能具有不同的欄位。
簡單的模型可以如此定義。
type Article struct { Id bson.ObjectId `bson:"_id,omitempty"` Title string `bson:"title"` Content string `bson:"content"` }
使用了struct field tag
,參考golang英文wiki,還有這裡的golang spec。
其中Id
這個欄位是使用mongodb
自己生成的_id
欄位,omitempty
表示該欄位在序列化的時候只接受非零值(0,空slice,或者空map都算是零值),按照我的理解就是,如果Id
是0
,那麼過了Marshal
之後應該是見不到_id
這個欄位的。
這個設計保證了不會誤存go語言給Id
的預設值0
,造成鍵衝突。
bson:"<field_name>"
和json:"<field_name>"
類似,聲明瞭序列化後欄位的鍵名。
回到正題,簡單欄位如int32
float32
、string
都不需要特殊處理,時間可能是一個需要關注的地方。
type Article struct { Id bson.ObjectId `bson:"_id,omitempty"` CreatedAt time.Time `bson:"created_at"` UpdatedAt time.Time `bson:"updated_at"` Title string `bson:"title"` Content string `bson:"content"` }
注意的一個點是bson.MongoTimestamp
在我使用時出現了無法正確反序列化mongodb
查詢結果的問題,原因不明。資料是手動在mongo shell
裡插入的,使用new Date()
賦值了created_at
和updated_at
。有人知道怎麼回事的話請告訴我。
使用time.Time
就可以正常序列化了。
查詢
mgo
查詢基本思路是:建立連線(mgo.Dial
)、選擇資料庫(Session.DB
)、選擇集合(Database.C
)、設定條件(Collection.Find
)、取出結果(Query.All
)。
簡單例子如下。
func findSomething() {
sess, err := mgo.Dial("mongodb://localhost:27017")
if err != nil {
panic(err)
}
var result []Article
sess.DB("test").C("articles").Find(bson.M{"title": "mgo初接觸"}).All(&result)
fmt.Println(result)
}
和一般mongo
查詢一樣支援一些排序之類的操作。
Query.Sort
按照文件說法可以寫出這樣的查詢:Find(bson.M{}).Sort("-created_at")
,-
號表示降序。
Query.skip
可以跳過一定數量的結果,Query.One
表示只取一個元素,Query.Limit
限制查詢結果的數量等等...
寫入
寫入的基本操作是Collection.Insert
和Collection.Update
以及兩個變體Collection.UpdateId
以及Collection.UpdateAll
。
最基本的Collection.Insert
應該不用多解釋。
Collection.Update
按照文件描述,是查詢到匹配引數selector
條件的一個document
並更新。通常我們更新document
應該是用_id
欄位來唯一確定,顧名思義Collection.UpdateId
就是這樣一個便捷方法。
更新多個document
的時候就用到了Collection.UpdateAll
了。引數和Collection.Update
無異,selector
確定要更新的document
有哪些,update
引數則確定要更新到什麼樣子。