Go言語でMongoDBを使う
前回
でチュートリアル的なものを書きました.
今回は、具体的に使ってて気づいたことを書き留めます.
Goには継承は無いが埋め込みがある
埋め込みについては@tenntennさんがとてもわかりやすい記事を書かれております.
いつもありがとうございます.
で、こんな感じで保存してみます
package main
import (
"fmt"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
)
// Personに共通なものはここにまとめたいですよね
type Person struct {
ID bson.ObjectId `bson:"_id"`
Name string `bson:"name"`
Level int `bson:"level"`
}
func (p *Person) Greet() string {
return fmt.Sprintf("My name is %s.", p.Name)
}
// 派生したstructもつくりたいですよね
type Admin struct {
Person
Password string `bson:"password"`
Permissions []string `bson:"permissions"`
}
func main() {
session, _ := mgo.Dial("mongodb://localhost/test")
defer session.Close()
db := session.DB("test")
admin := &Admin{
Person{
bson.NewObjectId(),
"otiai10",
10,
},
"hoge",
[]string{"write", "read"},
}
db.C("people").Insert(admin)
}
埋め込みをそのままInsertすると?
> db.people.find().pretty();
{
"_id" : ObjectId("548eeef9a82a1de844454bd0"),
"person" : {
"_id" : ObjectId("548eeef9b537115caa000001"),
"name" : "otiai10",
"level" : 10
},
"password" : "hoge",
"permissions" : [
"write",
"read"
]
}
埋め込んだPerson
がperson
という名前のフィールドとしてドキュメントに保存されているのがわかります.
こともあろうかmongo的な_idが二つ作られちゃってて気持ち悪い状況です.
これが嫌なとき
bsonにはinline
というタグキーワードがあります.
inline Inline the field, which must be a struct or a map,
causing all of its fields or keys to be processed as if
they were part of the outer struct. For maps, keys must
not conflict with the bson keys of other struct fields.フィールドをインライン化します。プリミティブはダメです、structかmapじゃないとダメです。inlineフラグを使うと、そのstructのフィールドは、その外側のstructのフィールドとして処理されます。もしmapを使う場合は、外側のstruct含め、mapのkey名とフィールド名がかぶってはいけません。
とのこと
type Admin struct {
- Person
+ Person `bson:",inline"`
Password string `bson:"password"`
Permissions []string `bson:"permissions"`
}
そうすっと
> db.people.find().pretty();
{
"_id" : ObjectId("548ef20ab537115cef000001"),
"name" : "otiai10",
"level" : 10,
"password" : "hoge",
"permissions" : [
"write",
"read"
]
}
埋め込んだPerson
のフィールドがちゃんとトップレベルのフィールドになってドキュメントに保存されていることがわかります.
これ結構便利なので
「encoding/json
にもinline
タグあったらよくね?」っていうディスカッションがこちらになります.
次回があるなら
「RestAPIでリクエストの扱いとmongoの相性」か、もしくは「database/sql
を使った場合との比較」みたいなものをば.
(Go+MongoDB、わりといいものに見えてきました)