为结构找到 Gorm 无效字段
Gorm invalid field found for struct
我的数据库结构目标
one user can join many communities
and
one user can own a community
这是我想出的结构,正确吗?
type User struct {
gorm.Model
Communities []Community `gorm:"many2many:user_communities" json:"communities"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
type Community struct {
gorm.Model
Name string `json:"name"`
UserID uint `json:"userID"`
Users []User `gorm:"many2many:user_communities" json:"users"`
}
这是我的数据库设置
func ConnectMysql() {
// Connect to Mysql database based on the environment variable
dsn := os.Getenv("MYSQL_DSN")
database, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("Failed to connect to the database")
}
database.AutoMigrate(&models.User{})
database.AutoMigrate(&models.Community{})
DB = database
}
以及如何查询以检查用户是否属于某个社区?
到目前为止我想到了这个但是它不起作用,可能我上面的架构是错误的
func CreateQuestion() {
var community Community
var foundUser User
communityID = 1
userID = 1
// Find the community
if err := database.Mysql.Where("id = ?", communityID).First(&community).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Community does not exist"})
return
}
// Im not sure whether this query is to check whether the user belongs to the community with id 1 or not.
if err := database.Mysql.Preload("Community").Where("id = ?", userID).Find(&foundUser).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "user is not in the community"})
return
}
}
我得到的错误
[error] invalid field found for struct
github.com/testing-be/Community's field Users: define a valid foreign
key for relations or implement the Valuer/Scanner interface
也许您在结构中遗漏了 gorm.Model
?
type User struct {
gorm.Model
Communities []Community `json:"communities"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
type Community struct {
gorm.Model
Name string `json:"name"`
UserID uint `json:"userID"`
Users []User `gorm:"many2many:user_communities" json:"users"`
}
出现此错误的原因是 gorm 找不到定义关系的外键。
将 ID 字段添加到 User
和 Community
结构(或使用 gorm.Model
而不是 ID)。此外,还要为 Communities
字段添加 many2many
。
type User struct {
ID uint `json:"id"`
Communities []Community `gorm:"many2many:user_communities" json:"communities"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
type Community struct {
ID uint `json:"id"`
Name string `json:"name"`
UserID uint `json:"userID"`
Users []User `gorm:"many2many:user_communities" json:"users"`
}
默认情况下,gorm 会尝试这样解析关系:
// Join Table: user_communities
// foreign key: user_id, reference: users.id
// foreign key: community_id, reference: communities.id
如果 user_communities
table 中的外键名称不同,here 是您可以处理的方式。
关于Preload
函数,它接受的是字段名,而不是字段类型,所以代码应该是这样的:
var foundUser User
if err := database.Mysql.Preload("Communities").Where("id = ?", userID).First(&foundUser).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "user is not in the community"})
return
}
此代码加载与找到的用户有关系的所有社区。
编辑:
以下示例可帮助您确定特定用户是否属于特定社区:
//Raw query
userID := 1
communityID := 1
var found sql.NullBool
if err := database.Mysql.Raw("SELECT 1 FROM users u JOIN user_communities uc ON u.id = uc.user_id WHERE u.id = ? AND uc.community_id = ?", userID, communityID).Scan(&found).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "error happened"})
return
}
if found.Valid && found.Bool {
//user is part of the specified community
}
//With gorm functions
userID := 1
communityID := 1
var found sql.NullBool
if err := database.Mysql.Table("users u").Joins("JOIN user_communities uc ON u.id = uc.user_id").Where("u.id = ? AND uc.community_id = ?", userID, communityID).Select("1").Scan(&found).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "error happened"})
return
}
if found.Valid && found.Bool {
//user is part of the specified community
}
接下来是如何加载指定用户和指定社区的示例:
//Finds just the specified user and loads just a specified community
userID := 1
communityID := 1
var user User
err := database.Mysql.Preload("Communities", "id = ?", communityID).Joins("JOIN user_communities uc ON u.id = uc.user_id").Where("uc.community_id = ?", communityID).First(&user, userID).Error
// err could be gorm.ErrorNotFound, which means that a record is not found, so this needs to be checked before err != nil check
//Finds just the specified user, loads all user's communities, but makes sure that a user belongs to a specific community
userID := 1
communityID := 1
var user User
err := database.Mysql.Preload("Communities").Joins("JOIN user_communities uc ON u.id = uc.user_id").Where("uc.community_id = ?", communityID).First(&user, userID).Error
// err could be gorm.ErrorNotFound, which means that a record is not found, so this needs to be checked before err != nil check
我的数据库结构目标
one user can join many communities
and
one user can own a community
这是我想出的结构,正确吗?
type User struct {
gorm.Model
Communities []Community `gorm:"many2many:user_communities" json:"communities"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
type Community struct {
gorm.Model
Name string `json:"name"`
UserID uint `json:"userID"`
Users []User `gorm:"many2many:user_communities" json:"users"`
}
这是我的数据库设置
func ConnectMysql() {
// Connect to Mysql database based on the environment variable
dsn := os.Getenv("MYSQL_DSN")
database, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("Failed to connect to the database")
}
database.AutoMigrate(&models.User{})
database.AutoMigrate(&models.Community{})
DB = database
}
以及如何查询以检查用户是否属于某个社区?
到目前为止我想到了这个但是它不起作用,可能我上面的架构是错误的
func CreateQuestion() {
var community Community
var foundUser User
communityID = 1
userID = 1
// Find the community
if err := database.Mysql.Where("id = ?", communityID).First(&community).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Community does not exist"})
return
}
// Im not sure whether this query is to check whether the user belongs to the community with id 1 or not.
if err := database.Mysql.Preload("Community").Where("id = ?", userID).Find(&foundUser).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "user is not in the community"})
return
}
}
我得到的错误
[error] invalid field found for struct github.com/testing-be/Community's field Users: define a valid foreign key for relations or implement the Valuer/Scanner interface
也许您在结构中遗漏了 gorm.Model
?
type User struct {
gorm.Model
Communities []Community `json:"communities"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
type Community struct {
gorm.Model
Name string `json:"name"`
UserID uint `json:"userID"`
Users []User `gorm:"many2many:user_communities" json:"users"`
}
出现此错误的原因是 gorm 找不到定义关系的外键。
将 ID 字段添加到 User
和 Community
结构(或使用 gorm.Model
而不是 ID)。此外,还要为 Communities
字段添加 many2many
。
type User struct {
ID uint `json:"id"`
Communities []Community `gorm:"many2many:user_communities" json:"communities"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
type Community struct {
ID uint `json:"id"`
Name string `json:"name"`
UserID uint `json:"userID"`
Users []User `gorm:"many2many:user_communities" json:"users"`
}
默认情况下,gorm 会尝试这样解析关系:
// Join Table: user_communities
// foreign key: user_id, reference: users.id
// foreign key: community_id, reference: communities.id
如果 user_communities
table 中的外键名称不同,here 是您可以处理的方式。
关于Preload
函数,它接受的是字段名,而不是字段类型,所以代码应该是这样的:
var foundUser User
if err := database.Mysql.Preload("Communities").Where("id = ?", userID).First(&foundUser).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "user is not in the community"})
return
}
此代码加载与找到的用户有关系的所有社区。
编辑:
以下示例可帮助您确定特定用户是否属于特定社区:
//Raw query
userID := 1
communityID := 1
var found sql.NullBool
if err := database.Mysql.Raw("SELECT 1 FROM users u JOIN user_communities uc ON u.id = uc.user_id WHERE u.id = ? AND uc.community_id = ?", userID, communityID).Scan(&found).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "error happened"})
return
}
if found.Valid && found.Bool {
//user is part of the specified community
}
//With gorm functions
userID := 1
communityID := 1
var found sql.NullBool
if err := database.Mysql.Table("users u").Joins("JOIN user_communities uc ON u.id = uc.user_id").Where("u.id = ? AND uc.community_id = ?", userID, communityID).Select("1").Scan(&found).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "error happened"})
return
}
if found.Valid && found.Bool {
//user is part of the specified community
}
接下来是如何加载指定用户和指定社区的示例:
//Finds just the specified user and loads just a specified community
userID := 1
communityID := 1
var user User
err := database.Mysql.Preload("Communities", "id = ?", communityID).Joins("JOIN user_communities uc ON u.id = uc.user_id").Where("uc.community_id = ?", communityID).First(&user, userID).Error
// err could be gorm.ErrorNotFound, which means that a record is not found, so this needs to be checked before err != nil check
//Finds just the specified user, loads all user's communities, but makes sure that a user belongs to a specific community
userID := 1
communityID := 1
var user User
err := database.Mysql.Preload("Communities").Joins("JOIN user_communities uc ON u.id = uc.user_id").Where("uc.community_id = ?", communityID).First(&user, userID).Error
// err could be gorm.ErrorNotFound, which means that a record is not found, so this needs to be checked before err != nil check