Kristijan Ujevic
Kristijan Ujevic

Reputation: 63

Gorm Joins not mapping to models

I'm trying to optimize my app by using sql joins instead of Preload(). But i've ran into an issue where the joined table in the model is always empty.

In desperation i've opened a new project and found some simple sample code, and again the same problem. If you run the code below you'll see that the joined table is always an empty array.

Am i doing something wrong?

import (
"fmt"
"log"

"github.com/jinzhu/gorm"
_ "github.com/lib/pq"
)

type Language struct {
    ID   uint `gorm:"primary_key"`
    Name string
}

type Movie struct {
    ID         uint `gorm:"primary_key"`
    Title      string
    Language   Language
    LanguageID uint
}

type Artist struct {
    ID     uint `gorm:"primary_key"`
    Name   string
    Movies []Movie `gorm:"many2many:artist_movies"`
}

func createArtists() {
    langs := []Language{{Name: "english"},
        {Name: "tamil"},
        {Name: "french"}}

    for i, _ := range langs {
        if err := db.Create(&langs[i]).Error; err != nil {
            log.Fatal(err)
        }
    }

    movies := []Movie{
        {Title: "Nayagan", Language: langs[1]},
        {Title: "Anbe sivam", Language: langs[1]},
        {Title: "3 idiots", Language: langs[2]},
        {Title: "Shamithab", Language: langs[2]},
        {Title: "Dark Knight", Language: langs[0]},
        {Title: "310 to Yuma", Language: langs[0]},
    }
    for i, _ := range movies {
        if err := db.Create(&movies[i]).Error; err != nil {
            log.Fatal(err)
        }
    }

    artists := []Artist{
        {Name: "Madhavan", Movies: []Movie{movies[1],movies[2]}},
        {Name: "Kamal Hassan", Movies: []Movie{movies[0], movies[1]}},
        {Name: "Dhanush", Movies: []Movie{movies[3]}},
        {Name: "Aamir Khan", Movies: []Movie{movies[2]}},
        {Name: "Amitabh Bachchan", Movies: []Movie{movies[3]}},
        {Name: "Christian Bale", Movies: []Movie{movies[4], movies[5]}},
        {Name: "Russell Crowe", Movies: []Movie{movies[5]}},
    }

    for i, _ := range artists {
    if err := db.Create(&artists[i]).Error; err != nil {
        log.Fatal(err)
        }
    }
}

var db *gorm.DB

func main() {
    var err error
    db, err = gorm.Open("postgres", "user=admin password=1234 dbname=test sslmode=disable")
if err != nil {
    log.Fatal(err)
}
db.AutoMigrate(new(Language), new(Movie), new(Artist))
db.LogMode(true)

createArtists()

var artists []Artist

if err = db.Joins("JOIN artist_movies on artist_movies.artist_id=artists.id").
    Joins("JOIN movies on movies.id=artist_movies.movie_id").
    Joins("JOIN languages on movies.language_id=languages.id").
    Where("languages.name=?", "tamil").
    Group("artists.id").Find(&artists).Error; err != nil {
    log.Fatal(err)
}
for _, ar := range artists {
    fmt.Println(ar.Movies)
}

artists = []Artist{}
if err = db.Joins("JOIN artist_movies on artist_movies.artist_id=artists.id").
    Joins("JOIN movies on artist_movies.movie_id=movies.id").Where("movies.title=?", "Nayagan").
    Group("artists.id").Find(&artists).Error; err != nil {
    log.Fatal(err)
}

for _, ar := range artists {
    fmt.Println(ar.Movies)
}

artists = []Artist{}

if err = db.Joins("JOIN artist_movies on artist_movies.artist_id=artists.id").
    Joins("JOIN movies on artist_movies.movie_id=movies.id").
    Where("movies.title in (?)", []string{"3 idiots", "Shamitabh", "310 to Yuma"}).
    Group("artists.id").Find(&artists).Error; err != nil {
    log.Fatal(err)
}
for _, ar := range artists {
    fmt.Println(ar.Movies)
}

}

Upvotes: 5

Views: 10813

Answers (1)

Lu.nemec
Lu.nemec

Reputation: 512

Gorm doesn't automatically load data into related tables. You have to use Preload("table") for that in your query. When creating records with related fields, use associations.

Docs

Gorm doesn't currently support preloading with JOINS, you have to create SQL with SQL Builder and map the resulting rows to your structures.

Upvotes: 2

Related Questions