gorm 联合查询的时候如何只查询指定字段?

2019-08-19 11:11:49 +08:00
 imherer

有如下三个 struct

type Article struct {
	gorm.Model
	CategoryID int            `json:"-" gorm:"not null"`
	Category   Category       `json:"category" gorm:"ForeignKey:CategoryID;`
	Title      string         `json:"title" gorm:"not null;type:varchar(100);"`
	AuthorID   int            `json:"-"`
	Author     Author         `gorm:"ForeignKey:AuthorID"`
	Content    string         `json:"content" gorm:"not null;type:text"`
}
type Category struct {
	ID   uint   `json:"id" gorm:"primary_key;AUTO_INCREMENT"`
	Name string `json:"name" gorm:"type:varchar(100)"`
	Max  int    `json:"max"`
}
type Author struct {
	gorm.Model
	Name string `json:"name"`
}

想实现如下的 SQL 应该如何写呢?

SELECT a.id,a.title,b.name as category,c.name as author FROM article a, category b, author c WHERE a.category_id=b.id AND a. author_id = c.id AND a.category_id =1

// 这样是查询出了三张表的所有字段,Select 好像只支持当前表的字段
// list := []Article{}
// mysql.Preload("Author").Preload("Category").Find(&list, "category_id=?", 1)

8554 次点击
所在节点    Go 编程语言
11 条回复
janxin
2019-08-19 11:28:52 +08:00
gorm 的 perload 不是联合查询吧

gorm.io/docs/sql_builder.html#Run-Raw-SQL 试试这个?
imherer
2019-08-19 11:35:03 +08:00
@janxin Preload 是联合查询的

我现在也的解决方案也是 raw
janxin
2019-08-19 11:54:33 +08:00
@imherer gorm.io/docs/preload.html#Preload 文档不是这么说的吧
xiaoyiyu
2019-08-19 14:18:06 +08:00
keepeye
2019-08-19 14:34:52 +08:00
Custom Preloading SQL
You could custom preloading SQL by passing in func(db *gorm.DB) *gorm.DB, for example:

db.Preload("Orders", func(db *gorm.DB) *gorm.DB {
return db.Order("orders.amount DESC")
}).Find(&users)
//// SELECT * FROM users;
//// SELECT * FROM orders WHERE user_id IN (1,2,3,4) order by orders.amount DESC;
ylsc633
2019-08-19 15:08:14 +08:00
不知道你们用 gorm 有没有发现 gorm 关联查询有个问题!

比如 user role permission 三个表, user 与 role 是多对多的关系, role 与 permission 是多对多的关系!

如果我想查 模糊查询 user 的 name like test, 然后限定 角色 role = default 的

在 gorm 里用 Preload 会出现两条 sql, 一条是 select * from user where username like %test%

第二条是 select * from role inner join user_role on user_role.role_id = role.id where role.name = default

然后 gorm 会把第二条的数据关联回第一条的结果上!

可是这样跟要求是不一致的!

不知道你们有没有发现这个!

所以真的有这种需求的时候,建议 手写 sql 或者 join
dongya
2019-08-19 16:19:27 +08:00
直接写 sql 呀
shingle
2019-08-19 16:32:38 +08:00
db.Table("article a").Select("a.id,a.title,b.name as category,c.name as author").Joins("left join category b on a.category_id = b.id").Joins("left join author c on a.author_id = c.id AND a.category_id =1").Scan()
imherer
2019-08-19 17:08:08 +08:00
@ylsc633 是的。简单的用 gorm,复杂的就直接手写 sql 了
ylsc633
2019-08-19 17:45:03 +08:00
@imherer 手写 sql 有个不好的就是 得写死 表名!

万一改了表名(改表名,换了新表,添加修改前缀等)就得哭!

除非调用 tablename 方法,不过这样就得拼凑字符串了......
imherer
2019-08-19 19:17:20 +08:00
@ylsc633 对的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/593073

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX