我有一个json类型的专栏.在json数据中,有几列.我们希望能够使用等于、LIKE和NOT EQUAL操作符查询数据.有什么办法解决这个问题吗?

请记住,在本例中,列名也是动态的,因此我不能在WHERE子句中对其进行硬编码.

func applyServerLogsQuery(db *gorm.DB, logType api.LogDestination_LogType, req *logs.GetLogsRequest) (*gorm.DB, error) {
    // set log type
    db = db.Where("log_type = ?", logType)

    // check for time
    if !req.StartTime.IsZero() {
        db = db.Where("time_stamp >= ?", req.StartTime)
    }

    if !req.EndTime.IsZero() {
        db = db.Where("time_stamp <= ?", req.EndTime)
    }

    // process filters
    for _, filter := range req.Filters {
        if len(filter.Values) == 0 {
            continue
        }

        property := filter.PropertyInfo.Name
        value := filter.Values[0]

        switch filter.FilterType {
        case logs.FilterTypeRegex:
            db = db.Where("log->>$? like ?", property, value)

        case logs.FilterTypeShould:
            db = db.Where("log->>$? = ?", property, value)

        case logs.FilterTypeExclude:
            db = db.Where("log->>$? != ?", property, value)
        }

        /*
            prefix := fmt.Sprintf("log->>'$.%s'", filter.PropertyInfo.Name)
            value := filter.Values[0]
            queryString := fmt.Sprintf("log->>'$.%s' like '%s'", filter.PropertyInfo.Name, value)

            log.Printf("Prefix %s value %s query %s", prefix, value, queryString)

            switch filter.FilterType {
            case logs.FilterTypeRegex:
                db = db.Where(queryString)
            }
        */
    }

    // handle order by time
    orderStr := "time_stamp"
    if req.OrderDesc {
        orderStr = fmt.Sprintf("%s desc", orderStr)
    } else {
        orderStr = fmt.Sprintf("%s asc", orderStr)
    }
    db = db.Order(orderStr)

    // handle limit
    db = db.Limit(int(req.Limit))

    return db, nil
}

MySQL查询格式错误- SELECT*FORserver_logs WHERE LOG_TYPE=2 AND TIME_STAMP&gt;=‘2023-03-10 15:55:14.304’AND TIME_STAMP&lt;=‘2023-03-10 15:55:24.441’AND LOG-&>;&gt;$‘Severity’=‘High’ORDER BY TIME_STAMP Desc

问题在于转义--它应该是对数的--&gt;&gt;‘$.Severity’

如果我try 使用fmt.Sprint tf构造查询字符串,它会起作用,但当然,我们会受到SQL注入的影响.

prefix := fmt.Sprintf("log->>'$.%s'", filter.PropertyInfo.Name)
            value := filter.Values[0]
            queryString := fmt.Sprintf("log->>'$.%s' like '%s'", filter.PropertyInfo.Name, value)

            log.Printf("Prefix %s value %s query %s", prefix, value, queryString)

            switch filter.FilterType {
            case logs.FilterTypeRegex:
                db = db.Where(queryString)
            }

在上面的例子中,生成了正确的查询字符串.

谢谢你调查这件事.

推荐答案

->->>运算符不接受表达式或参数.它们只接受JSON路径作为字符串文字.所以你一定要用JSON_UNQUOTE(JSON_EXTRACT(...)).

我建议在将JSON路径作为参数传递之前,在GO表达式中设置它的格式.

db = db.Where("json_unquote(json_extract(log, ?)) like ?",
  "$."+property, value)

另一种方法是使用conat()格式化JSON路径,并将属性单独作为参数传递.

db = db.Where("json_unquote(json_extract(log, concat('$.', ?))) like ?",
  property, value)

Mysql相关问答推荐

用于将重复行的唯一列值作为单独列获取的SQL查询

数组上的MySQL、JSON_CONTAINS用法

JPA对具有动态键和动态值的JSON列的原生查询

DJANGO 使用原始 MYSQL 查询计算记录数并在 html 模板中使用结果

警告:MYSQL_OPT_RECONNECT 已弃用

从三个不同的表中生成两列,并使用分组变量计算这些列的比率

MySQL如何在小时和分钟之间 Select 时间

Django中的MYSQL查询等效

如何从将分钟、天、月和年存储在不同列中的表中查询数据

巨大的未分区 MySQL 表问题

JOOQ:如何将 POJO 列序列化为 JSON

如何显示患者预约中的专业人员姓名?

Mysql 相等性反对 false 或 true

Golang Gorm 没有创建带有约束的表

MySQL查询根据同一表中其他字段的值更新表中的字段

Python MYSQL 更新语句

这是将表单数据插入 MySQL 数据库的安全方法吗?

MySQL - 在 MySQL UPDATE 或 SELECT 查询中使用 If Then Else

Yii2 如何进行 where AND 或 OR 条件分组?

在 MySQL Workbench 中导出超过 1000 条记录的查询结果