如何查询包含对象数组的MySQL JSON列

时间:2019-03-26 20:52:11

标签: mysql sql json

我有一个MySQL(v5.7)数据库,该数据库具有一个名为 deals 的表,该表包含一个名为 status 的JSON列。

状态包含以下格式的数据(以交易 id = 29表示)(为该格式表示歉意):

{
    "trackStatus":
    [
        {
            "date":[],
            "notes":[],
            "value":"0",
            "isChecked":false
        },
        {
            "date":["2019-03-25T17:42:45-04:00"],
            "notes":[],
            "value":4,
            "isChecked":true
         }
    ],
    "nextStatusIndex":0, 
    "currentDealStatus":4
}

我正在尝试查询trackStatus = 4 value被检查的to find out if it数组。

通过阅读MySQL参考,我的理解是我需要使用JSON_EXTRACT函数来获取数据。

在下面的一些示例中,我如下测试了查询,以查看是否可以返回trackStatus

SELECT JSON_EXTRACT(status, '$.trackStatus') 
FROM deals 
WHERE deals.id = 29

这有效并返回trackStatus。但是,当我尝试对此进行扩展以在trackStatus中专门针对isChecked进行查询时,它不会返回值(不是null,而是空白)。

SELECT JSON_EXTRACT(status, '$.trackStatus', '$.isChecked') 
FROM deals 
WHERE deals.id = 29 AND JSON_EXTRACT(status, '$.trackStatus', '$.value') = 4

我尝试了无数种不同的查询,以至于我绕圈走。

我意识到问题出在trackStatus上,因为如果删除该数组,我可以查询nextStatusIndex并且它可以工作。但是,有了数组,就没有了。

因此,我希望有人能够告诉我如何/是否可以使用MySQL查询(在trackStatusnextStatusIndex中)来查询此JSON,以及数据的格式化方式。

1 个答案:

答案 0 :(得分:1)

在MySQL 8.0中,可以使用function JSON_TABLE()将内部JSON数组转换为记录集,然后对其进行检查。

这是5.7版的解决方案,它依赖于JSON_SEARCH() and JSON_EXTRACT()

此查询将为属性isChecked设置为trackStatus的{​​{1}}数组中(第一个)元素的属性value的值:

4

将样本数据保存在this DB fiddle中,将返回:

SELECT JSON_EXTRACT(
    status, 
    REPLACE(
        REPLACE(
            JSON_SEARCH(status, 'all', '4', '', '$.trackStatus[*].value'), 
        '"', ''), 
    '.value', '.isChecked')
) isCheckedAtValue4
FROM deals WHERE deals.id = 29;

详细信息

您可以使用| isCheckedAtValue4 | | ----------------- | | true | 在属性JSON_SEARCH设置为trackStatus的数组value中查找(第一个)元素的路径:

4

使用测试数据,通常会返回:SELECT JSON_SEARCH(status, 'one', '4', '', '$.trackStatus[*].value') FROM deals WHERE deals.id = 29;

我们可以操纵路径字符串将其指向同一数组元素的属性"$.trackStatus[1].value"。周围的双引号也需要删除:

isChecked

这将返回:SELECT REPLACE( REPLACE( JSON_SEARCH(status, 'one', '4', '', '$.trackStatus[*].value'), '"', ''), '.value', '.isChecked'), FROM deals WHERE deals.id = 29;

最后,可以将该表达式作为$.trackStatus[1].isChecked的参数来给出。