So I have two tables in application: users
and posts
. I'd like to implement a liking functionality where a user can like a post. To do this I created the following table:
type Like struct {
PostId string `json:"post_id"`
UserId string `json:"user_id"`
CreatedAt time.Time `json:"created_at"`
}
My questions is how can I make it so when I AutoMigrate
the Like
model, foreign keys are setup automatically?
I have tried using the gorm:"foreignKey:Post"
and gorm:"foreignKey:User"
struct tags in their respective spots but they don't do anything.
How could I get this to work? Thank you!
CodePudding user response:
To set up foreign keys in the Like model using GORM, you will need to use the gorm:"ForeignKey::" struct tag. Here is how you can set up foreign keys for the PostId and UserId columns:
type Like struct {
ID int gorm:"primary_key"
PostId string gorm:"type:varchar(255);index;foreignKey:Post" json:"post_id"
UserId string gorm:"type:varchar(255);index;foreignKey:User" json:"user_id"
CreatedAt time.Time json:"created_at"
}
This will create foreign key constraints on the Like model that reference the Post and User tables. When you call db.AutoMigrate(&Like{}), GORM will automatically create the foreign key constraints in the database.
You can also specify the name of the foreign key column using the foreignKey::: struct tag. For example:
type Like struct {
ID int gorm:"primary_key"
PostId string gorm:"type:varchar(255);index;foreignKey:Post:post_id" json:"post_id"
UserId string gorm:"type:varchar(255);index;foreignKey:User:user_id" json:"user_id"
CreatedAt time.Time json:"created_at"
}
his will create foreign key constraints on the Like model that reference the Post and User tables, and name the foreign key columns post_id and user_id, respectively.
CodePudding user response:
As you are not following conventions (i.e. Id instead of ID, PostId instead of PostID) in naming you need to explicitly tell gorm which is the foreign key and referred to which property.
Here is the snippet. Github Link
Reference:
package storage2
import (
"log"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type Post struct {
Body string `gorm:"type:text"`
Id string `gorm:"type:uuid;primary_key"`
Likes []Like `gorm:"foreignkey:PostId;references:Id"`
User User `gorm:"foreignkey:UserId;references:Id"`
UserId string
}
type Like struct {
Id string `gorm:"type:uuid;primary_key"`
PostId string `gorm:"type:uuid;not null"`
User User `gorm:"foreignkey:UserId;references:Id"`
UserId string
}
type User struct {
Id string `gorm:"type:uuid;primary_key"`
Name string
}
func GormTest() {
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
})
if err != nil {
log.Fatal("could not open database")
}
err = db.AutoMigrate(&User{}, &Post{}, &Like{})
if err != nil {
log.Fatal("could not migrate database")
}
createTestData(db)
fetchData(db)
}
func createTestData(db *gorm.DB) {
users := []User{
{Id: "0b83313d-1f85-4093-8621-efd2f21419d3", Name: "Shahriar"},
{Id: "bddd6566-bcd2-4ad1-8eb9-65a23f5a9856", Name: "John"},
{Id: "663c1328-dce2-4527-aecb-7fc478c229c2", Name: "Durand"}}
err := db.Create(&users).Error
if err != nil {
log.Println("failed to create user data")
}
like := Like{
Id: "45ba45fc-0900-4fcc-80dd-c394170b777b",
UserId: users[0].Id,
}
post := Post{
Id: "4cebb4c7-d44e-4160-a2df-a06f43211d45",
Body: "Test Post",
Likes: []Like{like},
UserId: users[1].Id,
}
err = db.Create(&post).Error
if err != nil {
log.Println("failed to crete post")
}
}
func fetchData(db *gorm.DB) {
post := Post{
Id: "4cebb4c7-d44e-4160-a2df-a06f43211d45",
}
if err := db.Preload("Likes").First(&post).Error; err != nil {
log.Println("failed to load post")
}
log.Println(post)
}