我有一个JSON对象数组,想返回一个特定的节点。为了简化我的问题,可以说数组看起来像这样:
[
{"Race": "Orc", "strength": 14},
{"Race": "Knight", "strength": 7},
...
]
例如,我想知道骑士的实力。
函数JSON_SEARCH
返回路径'$[1].Race'
,使用path operator可以得到优势。有没有办法将两者结合起来,所以我可以做下面的事情?
SELECT someFunc(myCol,'$[*].Race','Orc','$.strength') AS strength
FROM myTable
我正在使用MySQL 8.0.15。
答案 0 :(得分:2)
本质上,您的意思是将selection and projection应用于JSON文档的数组元素和对象字段。您需要执行WHERE子句之类的操作来选择数组中的“行”,然后执行诸如选择一个字段(而不是您在选择条件中使用的字段)之类的操作。
这些是使用WHERE子句和列的SELECT-list在SQL中完成的,但使用JSON进行相同的操作就很难通过JSON_SEARCH()和JSON_CONTAINS()之类的功能轻松完成。
MySQL 8.0提供的解决方案是JSON_TABLE()函数,可将JSON文档转换为虚拟派生表-就像您已定义常规行和列一样。如果JSON是您所描述的格式(一个对象数组),那么它将起作用。
这是我通过将示例数据插入表中进行的演示:
create table mytable ( mycol json );
insert into mytable set mycol = '[{"Race": "Orc", "strength": 14}, {"Race": "Knight", "strength": 7}]';
SELECT j.* FROM mytable, JSON_TABLE(mycol,
'$[*]' COLUMNS (
race VARCHAR(10) PATH '$.Race',
strength INT PATH '$.strength'
)
) AS j;
+--------+----------+
| race | strength |
+--------+----------+
| Orc | 14 |
| Knight | 7 |
+--------+----------+
现在,您可以执行SELECT查询通常要做的事情,例如选择和投影:
SELECT j.strength FROM mytable, JSON_TABLE(mycol, '$[*]'
COLUMNS (
race VARCHAR(10) PATH '$.Race',
strength INT PATH '$.strength'
)
) AS j
WHERE j.race = 'Orc'
+----------+
| strength |
+----------+
| 14 |
+----------+
这有两个问题:
您需要每次 进行此操作,或者查询JSON数据,否则创建一个VIEW来执行此操作。
您说过,您不知道属性字段,但是要编写JSON_TABLE()查询,您必须指定要搜索的属性并在查询中进行投影。您不能将其用于完全未定义的数据。
我已经回答了很多有关在MySQL中使用JSON的类似问题。我观察到,当您想做这种事情时,将JSON文档像表一样对待,以便可以将WHERE子句中的条件应用于JSON数据中的字段,那么所有查询都会变得更加困难。然后,您开始觉得最好花几分钟时间定义属性,以便编写更简单的查询。
答案 1 :(得分:2)
在 SQL 5.7 中有一种方法可以解决这个问题。我将一步一步地编写解决方案。目标是找到骑士的力量。
我将使用与上一篇文章相同的示例表:
create table mytable ( mycol json );
insert into mytable set mycol = '[{"Race": "Orc", "strength": 14}, {"Race": "Knight", "strength": 7}]';
首先,获取仅包含种族的数组。
select json_extract(mycol, '$[*].Race') from mytable;
+----------------------------------+
| json_extract(mycol, '$[*].Race') |
+----------------------------------+
| ["Orc", "Knight"] |
+----------------------------------+
然后,在该数组中搜索 Knight(并取消引用)。
select json_unquote(json_search(json_extract(mycol, '$[*].Race'), 'one', 'Knight')) from mytable;
+------------------------------------------------------------------------------+
| json_unquote(json_search(json_extract(mycol, '$[*].Race'), 'one', 'Knight')) |
+------------------------------------------------------------------------------+
| $[1] |
+------------------------------------------------------------------------------+
找到索引后,从数组中获取该元素。
select json_extract(mycol, json_unquote(json_search(json_extract(mycol, '$[*].Race'), 'one', 'Knight'))) from mytable;
+---------------------------------------------------------------------------------------------------+
| json_extract(mycol, json_unquote(json_search(json_extract(mycol, '$[*].Race'), 'one', 'Knight'))) |
+---------------------------------------------------------------------------------------------------+
| {"Race": "Knight", "strength": 7} |
+---------------------------------------------------------------------------------------------------+
然后得到这个元素的强度。
select json_extract(json_extract(mycol, json_unquote(json_search(json_extract(mycol, '$[*].Race'), 'one', 'Knight'))), '$.strength') as strength from mytable;
+----------+
| strength |
+----------+
| 7 |
+----------+
您可以在其他字段上重复此操作以创建其他列。
答案 2 :(得分:-1)
查看JSON_CONTAINS(https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-contains),并在您的WHERE子句中使用它来标识符合您条件的记录。