【问题标题】:Find all json keys if their value meets a condition in mysql如果它们的值满足mysql中的条件,则查找所有json键
【发布时间】:2021-10-10 14:49:49
【问题描述】:

我在表中有一个 json 列,其中每行包含键值对,

{"100" : 1, "102" : 3, "103" : 3}

我想查询该列以获取所有值 = 3 的 JSON_KEYS。键将是未知的,因此我无法使用 JSON_EXTRACT。我的输出应该是,

JSON_ARRAY("102", "103")

我正在使用 AURORA MYSQL 5.7,因此无法使用 JSON_TABLE

【问题讨论】:

  • 如果您需要在 SQL 中执行如此复杂的操作,那么您不应该将数据存储在 JSON 中。如果你把它存储在普通的行和列中,那么这个任务在 SQL 中就变得很容易了。几乎任何时候您认为需要在 WHERE 子句中引用 JSON 列时,您都应该将此作为一个强有力的指标,您不应该为该数据使用 JSON。
  • 明白。问题是该表不在我的控制范围内并且正在生产中,因此我无法更改结构

标签: mysql sql json


【解决方案1】:

您所描述的,搜索 JSON 值并返回键,就是 JSON_SEARCH() 所做的。如果您在 MySQL 中使用 JSON 数据,您应该阅读所有内置 JSON 函数的文档。没有那么多,如果您熟悉这些选择,它将为您节省很多时间。

但是,有一个警告:JSON_SEARCH() doesn't work for searching integers or booleans。它只能搜索字符串值。

这是一个演示:

mysql> select json_search(cast('{"100" : 1, "102" : 3, "103" : 3}' as json), 'all', 3) as `keys`;
+------+
| keys |
+------+
| NULL |
+------+

未找到匹配项。

但如果我将 3 值更改为字符串,它会起作用:

mysql> select json_search(cast('{"100" : 1, "102" : "3", "103" : "3"}' as json), 'all', '3') as `keys`;
+----------------------------+
| keys                       |
+----------------------------+
| ["$.\"102\"", "$.\"103\""] |
+----------------------------+

鉴于您的 JSON 数据存储整数值,我能想到的唯一解决方案是:

  • 获取所有数据到您的客户端应用程序中,将 JSON 文档反序列化为哈希数组,然后逐一搜索。

  • 创建另一个倒排索引表:

    CREATE TABLE jsonkeys_by_value (
      value int not null,
      id int not null, -- references the primary key of your table
      json_key int not null, -- references a key in the JSON document
      PRIMARY KEY (value, id, json_key) 
    );
    

    然后手动搜索一次所有 JSON 数据,在此表中填充对找到的每个值的每次出现的反向引用。然后就可以搜索了:

    SELECT ...
    FROM jsonkeys_by_value AS v
    JOIN your_table_with_json AS t USING (id) 
    WHERE value = 3;
    

    但这仍然不能告诉您哪些键的值为 3,只是 JSON 文档中有一个或多个值为 3 的键。至少它缩小了搜索范围,但您仍然需要使用应用程序代码检查 JSON 文档。

您也不能使用generated column,因为您说 JSON 键是可变的。

您可以使用正则表达式找出 如果 JSON 包含值 3,但这不会告诉您相应的键。 MySQL 8.0 之前没有 REGEXP_REPLACE() 函数,目前还没有基于 MySQL 8.0 的 Amazon Aurora 版本。

还有一个警告:Amazon Aurora 没有与 MySQL 5.7 完全兼容的 JSON 实施。他们在某个时候分叉了 MySQL 5.7 代码,因此他们缺少一些错误修复和功能。上次我检查时,我知道至少缺少 JSON_ARRAYAGG() 和 JSON_OBJECTAGG() 函数。这些功能是在 MySQL 5.7.22 版本中实现的,而 Aurora 没有这些功能。 Aurora 不是开源的,所以如果不仔细测试我们不知道它还缺少哪些其他功能。

【讨论】:

  • 感谢您的详细解释。确实,Aurora 缺少很多 json 功能,并且还没有基于 MySQL 8.0,因此 json_table 也不支持。我想我现在会采用你创建倒置表的方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多