gormを使って入れ子構造のオブジェクトを配列で取得したい

投稿者: Anonymous

例えば以下の構造体のデータベース

type Track struct{
    ID int
    Name string
    Artist Artist
    ArtistID int
}
type Artist struct{
    ID int
    Name string
}

があったとして、

普通に

var tracks []Track
db.Find(&tracks)

とすると 入れ子になっているArtistはnilになります。

このような場合tracksのArtistもまとめて取得するにはどうすればいいのでしょうか。
例えばtrack Trackというオブジェクトなら https://github.com/jinzhu/gorm#has-one の方法で取得できそうですが、配列として取得する方法がわかりません。ご教授いただけないでしょうか。

解決

gorm の has-one ではなく、単純に select * from artists where id = tracks.artist_id; に相当する処理で取得するのはどうでしょうか。

// Sample records
var tracks = []Track{
    {
        Name: "Let's Golang !",
        Artist: Artist{
            Name: "Gopher",
        },
    },
    {
        Name: "Happy Gopher",
        Artist: Artist{
            Name: "Golang masters",
        },
    },
}

func main() {
    db, _ := gorm.Open("sqlite3", "gorm.db")
    db.CreateTable(Track{}, Artist{})

    // Insert
    for _, s := range tracks {
        db.Create(&s)
    }

    // Select
    var selected []Track
    db.Find(&selected)

    // SELECT * FROM artists WHERE id = tracks.artist_id;
    for i, s := range selected {
        db.Where("id = ?", s.ArtistID).Find(&selected[i].Artist)
        fmt.Printf("%#vn", selected[i])
    }

    db.Close()
}

追記

has-one を使う方法も載せておきます(こちらの方が解り易いかもしれません)。

for i, s := range selected {
  db.Model(&s).Related(&selected[i].Artist, "ArtistID")
  fmt.Printf("%#vn", selected[i])
}

"ArtistID""artist_id"(DB テーブルのカラム名)でも問題ありません。

Model() で指定するテーブル(tracks)と Related() で指定するテーブル(artist) とを関連付けるカラム名(ArtistID or artist_id)を指定します。ただ、前述の Where(...).Find(...) と同様に 1 レコードづつ処理を行う必要があります。

回答者: user9156

Leave a Reply

Your email address will not be published. Required fields are marked *