如何在PostgreSQL中用GORM Raw查询数组?遇类型不支持错误
解决GORM Raw SQL映射json_agg到[]string报错的问题
问题原因
json_agg(k.name)返回的是PostgreSQL的JSON类型对象,而GORM默认无法直接将JSON类型自动映射到Go原生的[]string切片,因此抛出unsupported data type: &[]错误。
解决方案
方案一:改用array_agg替代json_agg
PostgreSQL的array_agg函数会直接返回text[]类型(字符串数组),GORM可以直接将其映射到Go的[]string字段,无需额外处理。同时为了避免无匹配关键词时返回NULL,可以用COALESCE函数默认返回空数组。
修改后的SQL语句:
SELECT a.article_id, a.title, a.created_at, a.content, u.name AS author, c.name AS category, sc.name AS sub_category, COALESCE(array_agg(k.name), '{}'::text[]) AS keywords, unit.name AS unit FROM articles a LEFT JOIN users u ON a.user_id = u.user_id LEFT JOIN categories c ON a.category_id = c.categ_id LEFT JOIN sub_categories sc ON a.sub_category_id = sc.sub_categ_id LEFT JOIN article_keywords ak ON a.article_id = ak.article_refer_id LEFT JOIN keywords k ON ak.keyword_refer_id = k.keyword_id LEFT JOIN units unit ON a.unit_id = unit.unit_id WHERE a.article_id = ? AND a.is_posted = true GROUP BY a.article_id, u.name, c.name, sc.name, unit.name
方案二:自定义类型实现Scanner接口
如果必须保留json_agg(比如需要返回JSON格式的数组),可以通过自定义Go类型并实现sql.Scanner接口,让GORM能够正确解析JSON数据到[]string。
- 定义自定义类型:
type StringArray []string
- 实现
sql.Scanner接口:
import "encoding/json" import "fmt" func (sa *StringArray) Scan(value interface{}) error { var bytes []byte switch v := value.(type) { case []byte: bytes = v case string: bytes = []byte(v) default: return fmt.Errorf("无法解析类型 %T 到 StringArray", value) } return json.Unmarshal(bytes, sa) }
- 修改结构体字段类型:
type GetArticleByID struct{ ID string `json:"article_id" gorm:"column:article_id"` Title string `json:"title"` Content string `json:"content"` CreatedAt time.Time `json:"created_at"` Author string `json:"author"` Category string `json:"category"` SubCategory string `json:"sub_category"` Keywords StringArray `json:"keywords"` Unit string `json:"unit"` }
这样执行原有的Raw SQL语句时,GORM会自动调用自定义的Scan方法将JSON数组解析为StringArray(本质仍是[]string),正常映射到结构体字段。
内容的提问来源于stack exchange,提问作者Rafi Azzaky
相关产品推荐
相关产品推荐

