0Pricing
Go Academy · レッスン

関連付け

リレーションシップをモデル化します

「関連付け」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

リレーションシップのモデル化

GORMのアソシエーションは、テーブル間のリレーションシップを構造体のフィールドに対応付けます。種類は、has one、has many、belongs to、many to manyの4つです。

  • 外部キーを構造体のフィールドとして表現します
  • 関連データを自動的に読み込みます
  • 関連レコードをまとめて作成します

Has Many

ユーザーは複数の投稿を持ちます。親は子のスライスを保持し、子は親を参照する外部キーを保持します。

type User struct {
    gorm.Model
    Name  string
    Posts []Post
}

type Post struct {
    gorm.Model
    Title  string
    UserID uint
}

Belongs To

子の視点では、投稿はユーザーに属します。これを表現するには、User フィールドと UserID 外部キーを追加します。

type Post struct {
    gorm.Model
    Title  string
    UserID uint
    User   User
}

Has One

has-oneはhas-manyに似ていますが、関連するレコードが1つだけです。たとえば、ユーザーが1つのプロフィールを持つ場合です。子が外部キーを保持します。

type User struct {
    gorm.Model
    Profile Profile
}

type Profile struct {
    gorm.Model
    UserID uint
    Bio    string
}

Many To Many

ユーザーとロールは、結合テーブルを介して多対多で関連します。many2many タグでその結合テーブルを指定します。Rolesフィールドの後ろにバッククォートで gorm:"many2many:user_roles;" と記述します。

type User struct {
    gorm.Model
    // Roles field tag: gorm:"many2many:user_roles;"
    Roles []Role
}

type Role struct {
    gorm.Model
    Name string
}

Preload

デフォルトでは、関連データは読み込まれません。Preload を使うと、GORMが別のクエリでアソシエーションを取得するため、手動で別途検索する必要がなくなります。

var user User
db.Preload("Posts").First(&user, 1)
fmt.Println(len(user.Posts))

ネストしたPreload

ドット区切りのパスを使うと、複数の階層にわたってpreloadできます。1回のメソッドチェーンで、ユーザーの投稿と各投稿のコメントを読み込めます。

db.Preload("Posts.Comments").First(&user, 1)

実行可能なアソシエーションのシミュレーション

GORMにはデータベースが必要です。そのため、この実行可能な例では、メモリ上のスライスを使ってhas-manyのリレーションシップとpreloadをモデル化します。

package main

import "fmt"

type Post struct {
    ID     int
    UserID int
    Title  string
}

type User struct {
    ID    int
    Name  string
    Posts []Post
}

func preload(u *User, all []Post) {
    for _, p := range all {
        if p.UserID == u.ID {
            u.Posts = append(u.Posts, p)
        }
    }
}

func main() {
    u := User{ID: 1, Name: "Ada"}
    all := []Post{{1, 1, "Hello"}, {2, 1, "World"}, {3, 2, "Other"}}
    preload(&u, all)
    fmt.Printf("%s has %d posts\n", u.Name, len(u.Posts))
}

アソシエーションを伴う作成

Create の前にスライスフィールドを設定しておくと、GORMが親と子をまとめて挿入し、外部キーを自動的に設定します。

user := User{Name: "Ada", Posts: []Post{{Title: "Hi"}}}
db.Create(&user)

N+1問題

親をループして反復ごとに子を検索すると、親ごとに1回ずつクエリが発行され、N+1問題が発生します。Preload を使うと、関連データの取得を1回の追加クエリにまとめて解決できます。

アソシエーションモード

Association APIを使うと、外部キーを手動で扱わずに、関連レコードの追加、置換、削除、クリアを行えます。たとえば db.Model(&user).Association("Posts").Append(&post) のように記述します。

理解度チェック

アソシエーションに関する知識を確認しましょう。

まとめ

アソシエーションについて学びました。

  • has one、has many、belongs to、many2manyでモデル間のリレーションシップを表します
  • 外部キーはUserIDのような構造体フィールドです
  • Preloadはアソシエーションを読み込み、N+1問題を避けます
  • 子を持つ親を作成すると、外部キーが設定されます
  • アソシエーションモードでリレーションを追加、置換、クリアできます

よくある質問

「関連付け」レッスンは無料ですか?

はい。「関連付け」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「関連付け」で何を学びますか?

リレーションシップをモデル化します ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「関連付け」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. モデルとAutoMigrate
  2. CRUD操作
  3. 関連付け
  4. フックとスコープ
← Go Academyに戻る