LoginSignup
41
36

More than 5 years have passed since last update.

Go言語でMongoDB使う ②埋め込みとの相性

Last updated at Posted at 2014-12-15

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"
    ]
}

埋め込んだPersonpersonという名前のフィールドとしてドキュメントに保存されているのがわかります.
こともあろうか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、わりといいものに見えてきました)

41
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
36