Go gorm 检查一个模型是否与另一个模型相关联

Go gorm check a model is associated with another model

我有一个比赛模型

type Race struct {
    gorm.Model
    Title   string
    Date    string
    Token   string
    Heats   []Heat   `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
    Runners []Runner `gorm:"many2many:race_runners;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}

我想将跑步者添加到预赛中,但在这样做之前我想断言跑步者确实在比赛中

var race models.Race
if err := models.DB.Preload("Runners").Find(&race, "runners.id IN ?", []uint{runner.ID}).Error; err != nil {
    c.JSON(http.StatusNotFound, gin.H{"error": "Runner not in race!"})
    return
}

我收到以下错误

near "?": syntax error 

因为我在 Race 和 Runners 之间存在多对多关系,所以我怀疑我能否在传递给 Find 方法的条件下执行 runners.id。但我不确定如何实际做我想实现的目标。这是确保跑步者在加入比赛之前已经在比赛中。有什么建议吗?

where 查询要在 Preload 部分。然后你可以检查 len(fetchedRace.Runners) < 1,如果是,则跑步者不在该比赛中。

    fetchedRace := Race{}
    db.Preload("Runners", "runners.id = ?", runnerOne.ID).Find(&fetchedRace, race.ID)

完整的工作示例

package main

import (
    "fmt"
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
)

type Race struct {
    gorm.Model
    Title   string
    Date    string
    Token   string
    Runners []Runner `gorm:"many2many:race_runners;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}

type Runner struct {
    gorm.Model
    Name string
}

func main() {
    db, err := gorm.Open(sqlite.Open("many2many.db"), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }

    // Migrate the schema
    _ = db.AutoMigrate(&Race{}, &Runner{})

    raceOne := Race{
        Title: "Race One",
    }
    db.Create(&raceOne)

    runnerOne := Runner{
        Name: "Runner One",
    }
    runnerTwo := Runner{
        Name: "Runner Two",
    }

    db.Create(&runnerOne)
    db.Create(&runnerTwo)

    // Associate runners with race
    err = db.Model(&raceOne).Association("Runners").Append([]Runner{runnerOne, runnerTwo})

    // Fetch from DB
    fetchedRace := Race{}

    db.Debug().Preload("Runners", "runners.id = ?", runnerOne.ID).Find(&fetchedRace, raceOne.ID)
    if len(fetchedRace.Runners) < 1 {
        fmt.Println("error, runner not in race")
    }

    db.Delete(&raceOne)
    db.Delete(&runnerOne)
    db.Delete(&runnerTwo)
}

使用自定义 SQL 语句

这可以在一个 SQL 语句中完成,而且 gorm 的预加载不是很理想,所以如果你打算经常使用它,我可能会做这样的事情:

func isRunnerInRace(db *gorm.DB, runnerId uint, raceId uint) bool {
    count := 0
    db.Raw("SELECT COUNT(runner_id) FROM race_runners WHERE race_id = ? AND runner_id = ?", raceId,
        runnerId).Scan(&count)
    return count > 0
}