GORM 无法在 MySQL 中查询 boolean json 字段

问题描述 投票:0回答:1

注意:我只用 MySQL 测试过这个问题。

使用 bool 参数查询 json 字段内的属性时,查询返回 0 行。但是,如果将 bool 嵌入到 where 子句本身,则会得到 1 行。奇怪的是,调试器显示的生成的 SQL 是相同的。

下面的

results
属于
[]Account
类型:

type Account struct {
    gorm.Model
    UserID sql.NullInt64
    Number string
    Config AccountConfig `gorm:"type:json;serializer:json"`
}

type AccountConfig struct {
    Enabled bool   `json:"enabled"`
    Foo     string `json:"foo"`
    Bar     int64  `json:"bar"`
}

损坏的示例:

DB.Where("config->'enabled' = ?", true).Find(&results)
2024/04/30 11:20:10 /__REDACTED__/playground/main_test.go:108
[0.847ms] [rows:0] SELECT * FROM `accounts` WHERE config->'$.enabled' = true

工作示例:

DB.Where("config->'enabled' = true").Find(&results)
2024/04/30 11:20:10 /__REDACTED__/playground/main_test.go:108
[0.647ms] [rows:1] SELECT * FROM `accounts` WHERE config->'$.enabled' = true

我还尝试测试各种其他变体,例如使用

json_extract
和双箭头语法,如
config->>'$.enabled'
。嵌套值也会发生同样的情况,例如
config->'$.foo.enabled' = true

另外,请参阅 GORM 存储库中的我在 github 上的问题。我在问题中链接的我的拉取请求中提供了一系列测试用例。

mysql go go-gorm mysql-json
1个回答
0
投票

在 MySQL 中,JSON 文档中的布尔字段以标量 JSON 文档或标量字符串值的形式返回。您可以使用 mysql 客户端的

--column-type-info
选项看到这一点:

$ mysql --column-type-info

使用

->
返回 JSON 文档,即使该 JSON 文档仅包含单个标量值。

mysql> select config->'$.enabled' from Accounts;
Field   1:  `config->'$.enabled'`
Catalog:    `def`
Database:   ``
Table:      ``
Org_table:  ``
Type:       JSON
Collation:  utf8mb4_0900_ai_ci (255)
Length:     4294967292
Max_length: 4
Decimals:   31
Flags:      BINARY 

+---------------------+
| config->'$.enabled' |
+---------------------+
| true                |
+---------------------+

使用

->>
返回一个“不带引号”的值,它将 JSON 值转换为二进制字符串。

mysql> select config->>'$.enabled' from Accounts;
Field   1:  `config->>'$.enabled'`
Catalog:    `def`
Database:   ``
Table:      ``
Org_table:  ``
Type:       LONG_BLOB
Collation:  utf8mb4_0900_ai_ci (255)
Length:     4294967295
Max_length: 4
Decimals:   31
Flags:      BINARY 

+----------------------+
| config->>'$.enabled' |
+----------------------+
| true                 |
+----------------------+

无论哪种方式,从 JSON 中提取布尔值的结果都不会产生 SQL 布尔值,因此它无法与

true
或 Go 布尔值
true
进行比较。

我让它以这种方式工作:

db.Where("config->>'$.enabled' = ?", "true").Find(&results)

因此,我传递 Go string

"true"
,它将与从 JSON 提取运算符返回的 SQL 二进制字符串
'true'
进行比较。

我强烈建议您使用普通列而不是 JSON。使用 JSON 没有什么优势,而且它引入了很多奇怪的复杂性,就像这个例子一样。

© www.soinside.com 2019 - 2024. All rights reserved.