GORM查询PostgreSQL含指定元素的JSON数组字段问题
解决GORM+PostgreSQL JSON字段包含查询的问题
核心问题分析
你之前的写法存在两个关键问题:
- 手动拼接JSON字符串极易出现引号转义错误,还存在SQL注入风险
- 使用
attributes ->> 'email' = '[\"%v\"]'是直接匹配数组的完整字符串形式,只有当email数组完全等于目标数组时才会命中,无法实现"包含单个元素"的查询需求
正确实现方案
方案1:直接使用PostgreSQL的@>操作符(推荐)
复用SQL编辑器中验证有效的@>包含操作符,配合GORM参数绑定避免拼接错误:
import "encoding/json" // 构造合法的查询JSON结构 email := "eee@ccc.cc" queryCondition, _ := json.Marshal(map[string][]string{"email": {email}}) var authors []Author // 执行查询 db.Where("attributes @> ?", string(queryCondition)).Find(&authors)
通过json.Marshal自动生成标准JSON字符串,彻底规避手动转义引号的问题,同时保证查询逻辑与SQL编辑器完全一致。
方案2:使用JSON数组元素展开查询
如果需要更灵活的数组元素匹配逻辑,可以用jsonb_array_elements(针对jsonb类型)或json_array_elements(针对json类型)展开数组后匹配:
var authors []Author email := "eee@ccc.cc" db.Where("EXISTS (SELECT 1 FROM jsonb_array_elements(attributes->'email') AS elem WHERE elem::text = ?)", "\""+email+"\"").Find(&authors)
注:由于数组元素是字符串类型,elem::text会带引号,因此需要给目标邮箱字符串手动添加引号。
方案3:使用GORM Raw查询(正确参数绑定版)
如果必须使用Raw查询,不要手动拼接SQL,通过参数绑定传递查询条件:
import "encoding/json" email := "eee@ccc.cc" queryCondition, _ := json.Marshal(map[string][]string{"email": {email}}) var authors []Author db.Raw("SELECT * FROM authors WHERE attributes @> ?", string(queryCondition)).Scan(&authors)
额外注意事项
- 确认
attributes字段类型为json或jsonb(推荐用jsonb,查询性能更优) - 禁止使用
fmt.Sprintf拼接SQL语句,既容易出错,又会引入SQL注入风险
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

