golang如何构造pg, jsonb类型字段的动态查询条件

前言

postgres的jsonb字段,是支持查询的,并且查询速度不俗,因为是树形结构。我们知道查询某一个字段的值是这样写:

  • 查询username=kling的记录
where raw::jsonb ->> 'username' = 'kling'

那么,如何支持jsonb字段未知深度的子字段查询呢?比如:

  • 查询班主任叫张三的记录
where (raw::jsonb ->> class)::jsonb ->> 'master_name' = '张三'

甚至于深度很长。

实现:

// 生成动态的jsonb查询条件,不支持对子字段为数组的数据进行查询
// 条件:
// chain json字段链长度最少为2,其中第一个参数为主表字段,后面的参数为子字段
// condition 必须为数据库支持的条件判断符号
// value 为数据库支持的正常值
// 示例:
// chain = []string{"raw", "zonst_vx", "game_id}
// condition = "="
// value = "5"
// 输出: ((raw)::jsonb ->>'zonst_vx')::jsonb ->>'game_id'='5'
func JSONBWhere(chain []string, condition string, value string) (string) {
    
    
	return fmt.Sprintf("%s%s'%s'", countJSONB(chain), condition, value)
}


func point(field string, subfield string) string {
    
    
	return fmt.Sprintf("(%s)::jsonb ->>'%s'", field, subfield)
}

func countJSONB(chain []string) string {
    
    
	if len(chain) == 2 {
    
    
		return point(chain[0], chain[1])
	}

	sub := chain[:len(chain)-1]
	last := chain[len(chain)-1]
	return point(countJSONB(sub), last)
}

示例:

func TestJSONWhere(t *testing.T) {
    
    
	fmt.Println(JSONBWhere([]string{
    
    "raw", "zonst_vx", "game_id"}, "=", "5"))
}

输出:

((raw)::jsonb ->>'zonst_vx')::jsonb ->>'game_id'='5'

实际使用

  • gorm

type JSONQuery struct{
    
    
    Enable bool `json:"enable"`
	FieldName string `json:"field_name"`
	Condition string `json:"condition"`
	Value     string `json:"value"`
}
var jsonQuery = JSONQuery{
    
    
    Enable: true,
    FieldName: "raw.class.master_name",
    Condition: "=",
    Value: "张三",
}
if jsonQuery.Enable {
    
    
    db.Where(JSONBWhere(
        strings.Split(jsonQuery.FieldName, "."),
        jsonQuery.Condition,
        jsonQuery.Value,
    ))
}

猜你喜欢

转载自blog.csdn.net/fwhezfwhez/article/details/109078184