Search code examples
gogo-gormgraphql-go

golang, creating relation between 2 model and retrieve them with Preload using gorm


I am learning golang with gqlgen and gorm as orm, I am creating an app using with 2 models user and messages where the user has a list of messages, and the messages have sender and recipient. I have made them like the following

type User struct {
    ID        string     `json:"id" gorm:"primary_key;type:uuid;default:uuid_generate_v4()"`
    Username  string     `json:"username"`
    Email     string     `json:"email"`
    FirstName string     `json:"firstName"`
    LastName  string     `json:"lastName"`
    Messages  []*Message `json:"messages"`
    CreatedAt time.Time  `json:"created_at"`
    UpdatedAt time.Time  `json:"updated_at"`
    DeletedAt *time.Time `json:"deleted_at" sql:"index"`
}


type Message struct {
    ID          string     `json:"id" gorm:"primary_key;type:serial"`
    Title       string     `json:"title"`
    Body        string     `json:"body"`
    DueDate     time.Time  `json:"dueDate"`
    IsViewed    bool       `json:"isViewed" gorm:"default:false"`
    SenderID    string     `json:"senderId" gorm:"type:uuid"`
    Sender      *User      `json:"sender" gorm:"foreignkey:SenderID"`
    RecipientID string     `json:"recipientId" gorm:"type:uuid"`
    Recipient   *User      `json:"recipient" gorm:"foreignkey:RecipientID"`
    CreatedAt   time.Time  `json:"created_at"`
    UpdatedAt   time.Time  `json:"updated_at"`
    DeletedAt   *time.Time `json:"deleted_at" sql:"index"`
}

when I retrieve the messages data using Preload

var messages []*models.Message
err := db.
    Preload("Sender").
    Preload("Recipient").
    Find(&messages).Error
if err != nil {
    return nil, err
}
return messages, err

it works perfectly but my problem is when trying to retrieve the user with the messages preloaded.

var users []*models.User
err := db.
    Preload("Messages").
    Find(&users).Error
if err != nil {
    return nil, err
}
return users, err

this one gives me the following error can't preload field Messages for models.User

I know I might design my schema wrong if there's a better way to organize it I would appreciate it so much, thanks in advance.


Solution

  • I think you should separate messages in User to SentMessages and ReceivedMessages. Then you can specify foreign keys in User like that:

    SentMessages      []*Message `gorm:"foreignkey:SenderID" json:"sentMessages"`
    ReceivedMessages  []*Message `gorm:"foreignkey:RecipientID" json:"receivedMessages"`
    

    then use it as the following:

    var users []*models.User
    err := db.
    Preload("SentMessages").
    Preload("ReceivedMessages").
    Find(&users).Error
    if err != nil {
      return nil, err
    }
    return users, err
    

    that should work as you want