Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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、わりといいものに見えてきました)

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした