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
}
我有一个比赛模型
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
}