多值列表外键 sql gorm
Multi value list foreign key sql gorm
type Users struct {
ID int64
Email string
Permissions string
}
type UserPermissions struct {
ID int64
Description json.RawMessage
}
用户json应该是这样的:
{
"status": 200,
"data": {
"id": 1,
"email": "hello@hello.com",
"permisions": [{
"id":"1",
"description":"Create permission"
},
{
"id":"3",
"description":"Edit permission"
}]
}
}
我的用户权限中有以下字符串:
';1;3;5;7;'每个数字都是与UserPermissions相关的id struct/table
如何使用 gorm 将字符串与用户权限 table 匹配?。
我正在使用 mysql
您问题的答案(如果您使用 PostgreSQL 作为数据库)。
如果要查询给定用户记录的权限,给定其 ID
perms := []Permission{}
err := db.Joins("JOIN users u ON id::string IN STRING_TO_ARRAY(TRIM(';' FROM u.permissions), ';')").
Where("u.id = ?", userID).
Find(&perms).
Error
if err != nil {
log.Fatal(err) // or something like that
}
如您所见,我们正在使用一些函数进行时髦的连接,这些函数将权限字段清理并拆分为单独的字符串 ID。这是笨重、脆弱、超级缓慢和复杂的,并且源于您开始时的错误关系设计。
编辑:没关系,对于 MySQL 等效的解决方案要复杂得多,所以我建议您改用下面的建议。
更好的方法
如果您可以控制数据库设计,那么更好的方法是
通过不将 ID 数组存储为字符串,这在数据库设计中从来都不是一件好事,而是在 HasMany 关系的多边上使用外键*。
go 结构看起来像这样:
type User struct {
ID int64 `json:"id"`
Email string `json:"email"`
Permissions []UserPermission `json:"permissions"`
}
type UserPermissions struct {
ID int64 `json:"id"`
UserID int64 `json:"-"`
Description json.RawMessage `json:"description"`
}
// now you can use gorm to query the permissions that are related to a user
user := User{}
err := db.Preload("Permissions").First(&user, userID).Error
if err != nil {
log.Fatal(err)
}
// now you can access user.Permissions[i].Description for example.
// or marshal to json
out, err := json.Marshal(user)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(out))
*:我假设 User 和 UserPermission 之间的关系是一对多的。这很可能不是这种情况,多对多关系实际上是有意义的(一个用户可以拥有多个权限,一个权限可以属于多个用户)。如果是这种情况,概念是相同的,您应该能够按照 many to many relationships.
上的 Gorm 指南修改此解决方案
type Users struct {
ID int64
Email string
Permissions string
}
type UserPermissions struct {
ID int64
Description json.RawMessage
}
用户json应该是这样的:
{
"status": 200,
"data": {
"id": 1,
"email": "hello@hello.com",
"permisions": [{
"id":"1",
"description":"Create permission"
},
{
"id":"3",
"description":"Edit permission"
}]
}
}
我的用户权限中有以下字符串:
';1;3;5;7;'每个数字都是与UserPermissions相关的id struct/table
如何使用 gorm 将字符串与用户权限 table 匹配?。 我正在使用 mysql
您问题的答案(如果您使用 PostgreSQL 作为数据库)。
如果要查询给定用户记录的权限,给定其 ID
perms := []Permission{}
err := db.Joins("JOIN users u ON id::string IN STRING_TO_ARRAY(TRIM(';' FROM u.permissions), ';')").
Where("u.id = ?", userID).
Find(&perms).
Error
if err != nil {
log.Fatal(err) // or something like that
}
如您所见,我们正在使用一些函数进行时髦的连接,这些函数将权限字段清理并拆分为单独的字符串 ID。这是笨重、脆弱、超级缓慢和复杂的,并且源于您开始时的错误关系设计。
编辑:没关系,对于 MySQL 等效的解决方案要复杂得多,所以我建议您改用下面的建议。
更好的方法
如果您可以控制数据库设计,那么更好的方法是 通过不将 ID 数组存储为字符串,这在数据库设计中从来都不是一件好事,而是在 HasMany 关系的多边上使用外键*。
go 结构看起来像这样:
type User struct {
ID int64 `json:"id"`
Email string `json:"email"`
Permissions []UserPermission `json:"permissions"`
}
type UserPermissions struct {
ID int64 `json:"id"`
UserID int64 `json:"-"`
Description json.RawMessage `json:"description"`
}
// now you can use gorm to query the permissions that are related to a user
user := User{}
err := db.Preload("Permissions").First(&user, userID).Error
if err != nil {
log.Fatal(err)
}
// now you can access user.Permissions[i].Description for example.
// or marshal to json
out, err := json.Marshal(user)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(out))
*:我假设 User 和 UserPermission 之间的关系是一对多的。这很可能不是这种情况,多对多关系实际上是有意义的(一个用户可以拥有多个权限,一个权限可以属于多个用户)。如果是这种情况,概念是相同的,您应该能够按照 many to many relationships.
上的 Gorm 指南修改此解决方案