在Golang+PostgreSQL+sqlc项目中,如何让查询生成的结构体包含切片类型的嵌套关联对象
在Golang+PostgreSQL+sqlc项目中,如何让查询生成的结构体包含切片类型的嵌套关联对象
这个问题我之前也踩过坑!sqlc本身不会自动把关联查询返回的多行关联数据合并成切片类型,你当前的INNER JOIN会让每个投票对应一行结果,sqlc只能把每行映射成单个Vote结构体,而不是把同一个帖子的所有投票打包成切片。要实现你的需求,得换个方式处理查询和类型映射,具体步骤如下:
1. 修改SQL查询,用聚合函数打包投票数据
把原来的JOIN改成用json_agg聚合所有关联的投票记录成一个JSON数组,这样查询结果里只会返回一行数据,且投票数据是一个数组格式。同时注意改用LEFT JOIN避免帖子没有投票时查不到结果:
-- name: FindPostWithAuthorAndVotes :one SELECT posts.*, sqlc.embed(users), json_agg(votes) AS votes FROM posts INNER JOIN users ON users.id = posts.author_id LEFT JOIN votes ON votes.post_id = posts.id WHERE posts.id = $1 GROUP BY posts.id, users.id;
这里的json_agg(votes)会把当前帖子所有的投票行转换成一个JSON数组,GROUP BY posts.id, users.id确保同一个帖子和作者只返回一行结果。
2. 配置sqlc将JSON数组映射为Vote切片
接下来需要告诉sqlc,把查询返回的votes字段(JSON数组类型)映射成[]Vote类型。你可以在sqlc.yaml配置文件里添加类型覆盖规则:
version: "2" sql: - schema: "path/to/your/schema.sql" queries: "path/to/your/queries.sql" engine: "postgresql" gen: go: package: "db" out: "./db" overrides: - db_type: "jsonb" go_type: "[]db.Vote"
这样sqlc生成代码时,会把查询结果中的JSON数组字段自动转换成[]Vote类型。
额外注意事项
- 如果你的帖子可能没有投票,
json_agg会返回空数组而不是NULL,这样生成的Votes切片就是空切片,符合业务预期; - GROUP BY子句里的字段:因为
posts.id是主键,users.id是关联的主键,PostgreSQL允许只按这两个主键分组,不用列出所有非聚合字段; - 如果你不想全局覆盖jsonb到
[]Vote的映射,也可以在查询里给字段指定类型,或者用sqlc的自定义类型来单独处理。
这样调整后,生成的FindPostWithAuthorAndVotesRow结构体里的Votes字段就会是[]Vote类型啦!
备注:内容来源于stack exchange,提问作者zorojuro
相关产品推荐
相关产品推荐

