Home > Net >  How to create foreign keys in gorm?
How to create foreign keys in gorm?

Time:12-28

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:

  1. Belongs To
  2. Has Many
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)
}

  • Related