gpt4 book ai didi

sql - Golang gorm - 在不使用预加载的情况下获取关系

转载 作者:行者123 更新时间:2023-12-04 14:07:59 26 4
gpt4 key购买 nike

我是 gorm 和 golang 的新手,我正在处理查询以获取用户与对话中用户的对话。我的查询按预期工作,但我的问题是它没有带来用户的关系。

这是我的对话模型:

type Conversation struct {
ID uint `gorm:"primarykey"`
Users []User `gorm:"many2many:user_has_conversations;"`
Messages []ConversationMessage
}

这是我对数据库的请求:

var conversations []model.Conversation

result := r.db.Debug().Scopes(
pagination.Paginate,
scope.OrderByIDDescTable(conversationsTable),
).Joins(
"INNER JOIN `user_has_conversations` ON `user_has_conversations`.`conversation_id` = `conversations`.`id`",
).Joins(
"INNER JOIN `users` ON `users`.`id` = `user_has_conversations`.`user_id` AND `users`.`id` = ?",
UserID,
).Find(&conversations)

这个查询工作正常并正确地带来了用户的对话,但没有给我返回关系中的用户,当你查看它运行的查询时没有带来用户字段。

执行的查询:

SELECT `conversations`.`id` 
FROM `conversations`
INNER JOIN `user_has_conversations` ON `user_has_conversations`.`conversation_id` = `conversations`.`id`
INNER JOIN `users` ON `users`.`id` = `user_has_conversations`.`user_id` AND `users`.`id` = 1
ORDER BY `conversations`.`id` desc LIMIT 10;

在查询中可以看到查询是正确的,但是没有Select with the fields of relation。

如果我也将预加载与内部连接一起使用,确实可以提供正确的解决方案,但我认为当我已经连接来对用户进行预加载以再次获取用户时,这对性能没有好处。我希望能够通过连接获取它,而不是使用预加载。

这个例子有效,但如果有办法的话,我想在没有预加载的情况下使用它。

result := r.db.Debug().Scopes(
pagination.Paginate,
scope.OrderByIDDescTable(conversationsTable),
).Preload("Users").Joins(
"INNER JOIN `user_has_conversations` ON `user_has_conversations`.`conversation_id` = `conversations`.`id`",
).Joins(
"INNER JOIN `users` ON `users`.`id` = `user_has_conversations`.`user_id` AND `users`.`id` = ?",
UserID,
).Find(&conversations)

最佳答案

您可以通过为 gorm 实现自定义数据类型并在您的查询中使用它来从数据库中接收 users slice (见下文)来做到这一点。

自定义数据类型必须实现 Scanner 和 Valuer 接口(interface),因此 GORM 知道如何接收/将其保存到数据库中。 https://gorm.io/docs/data_types.html

type Users []User

func (u Users) Value() (driver.Value, error) {
return json.Marshal(u)
}

func (u *Users) Scan(src interface{}) error {
if bytes, ok := src.([]byte); ok {
return json.Unmarshal(bytes, u)
}
return errors.New(fmt.Sprint("Failed to unmarshal JSON from DB", src))
}

所以你的对话类型应该更新如下:

type Conversation struct {
ID uint `gorm:"primarykey"`
Users Users `gorm:"-"`
Messages []ConversationMessage
}

为了能够查询对话中所有参与的用户,我们需要使用 jsonb_aggjsonb_build_object 构建 json 对象

var conversations []model.Conversation

result := r.db.Debug().Scopes(
pagination.Paginate,
scope.OrderByIDDescTable(conversationsTable),
).
Select(conversationsTable + ".*," +
"jsonb_agg(
distinct jsonb_build_object(
'id', u.id,
'name', u.name,
//...
)
) as users").
Joins("INNER JOIN `user_has_conversations` ON `user_has_conversations`.`conversation_id` = `conversations`.`id`").
Joins("INNER JOIN `users` as u ON `u`.`id` = `user_has_conversations`.`user_id` AND `u`.`id` = ?", UserID).
Find(&conversations)

关于sql - Golang gorm - 在不使用预加载的情况下获取关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66796181/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com