当sqlite json具有值作为数组时如何正确提取

时间:2019-10-23 09:30:11

标签: json sqlite

我有一个sqlite数据库,在其中一个字段中,我存储了完整的json对象。我必须提出一些json选择请求。如果看到我的json ALL键的值是一个数组。 我们需要提取一些数据,例如“ pod”字段为fb的所有注释。当sqlite json的值作为数组时,如何正确提取?

从数据表中选择json_extract(data,'$。“ json”');给我全部东西。那我做 选择json_extract(data,'$。“ json” [0]')但我不想手动进行。我想迭代。

请提供一些我可以研究和研究的资料。 我的JSON

{
    "ALL": [{
            "comments": "your site is awesome",
            "pod": "passcode",
            "originalDirectory": "case1"
        },
        {
            "comments": "your channel is good",
            "data": ["youTube"],
            "pod": "library"
        },
        {
            "comments": "you like everything",
            "data": ["facebook"],
            "pod": "fb"
        },
        {
            "data": ["twitter"],
            "pod": "tw",
            "ALL": [{
                "data": [{
                    "codeLevel": "3"
                }],
                "pod": "mo",
                "pod2": "p"
            }]
        }
    ]
}



create table datatable ( path string , data json1 );
insert into datatable values("1" , json('<abovejson in a single line>'));

1 个答案:

答案 0 :(得分:1)

简单列表

在您的JSON表示注释的“简单”列表的情况下,您需要以下内容:

select key, value 
  from datatable, json_each( datatable.data, '$.ALL' )
 where json_extract( value, '$.pod' ) = 'fb' ;

使用您的示例数据返回:

2|{"comments":"you like everything","data":["facebook"],"pod":"fb"}

使用json_each()为输入JSON(datatable.data)的每个元素返回一行,起始于路径$.ALL(其中$是顶级,并且ALL是数组的名称:如果需要JSON对象的顶级,则可以省略路径)。就您而言,这将为每个评论条目返回一行。

该行的字段在SQLite文档的4.13. The json_each() and json_tree() table-valued functions中进行了记录:我们感兴趣的两个字段是key(大致来说是“行号”)和value (当前元素的JSON)。后者将包含名为commentpod等的元素。

因为我们只对pod等于fb的元素感兴趣,所以我们添加了where子句,使用json_extract()来获得pod(其中$.pod相对于value函数返回的json_each

嵌套列表

如果您的JSON包含嵌套元素(起初我没有注意到),那么您需要使用json_tree()函数而不是json_each()。后者只会迭代指定节点的直接子节点,而json_tree()将通过指定节点的 all 个子节点递归下降。

为了给我们一些数据,我在测试数据中增加了一个额外的元素:

create table datatable ( path string , data json1 );
insert into datatable values("1" , json('
    {
        "ALL": [{
                "comments": "your site is awesome",
                "pod": "passcode",
                "originalDirectory": "case1"
            },
            {
                "comments": "your channel is good",
                "data": ["youTube"],
                "pod": "library"
            },
            {
                "comments": "you like everything",
                "data": ["facebook"],
                "pod": "fb"
            },
            {
                "data": ["twitter"],
                "pod": "tw",
                "ALL": [{
                    "data": [{
                        "codeLevel": "3"
                    }],
                    "pod": "mo",
                    "pod2": "p"
                },
                {
                    "comments": "inserted by TripeHound",
                    "data": ["facebook"],
                    "pod": "fb"
                }]
            }
        ]
    }
'));

如果我们只是简单地切换为使用json_each(),那么我们会看到一个简单的查询(没有where子句)将返回源JSON的 all 元素:

select key, value 
  from datatable, json_tree( datatable.data, '$.ALL' ) limit 10 ;

ALL|[{"comments":"your site is awesome","pod":"passcode","originalDirectory":"case1"},{"comments":"your channel is good","data":["youTube"],"pod":"library"},{"comments":"you like everything","data":["facebook"],"pod":"fb"},{"data":["twitter"],"pod":"tw","ALL":[{"data":[{"codeLevel":"3"}],"pod":"mo","pod2":"p"},{"comments":"inserted by TripeHound","data":["facebook"],"pod":"fb"}]}]
0|{"comments":"your site is awesome","pod":"passcode","originalDirectory":"case1"}
comments|your site is awesome
pod|passcode
originalDirectory|case1
1|{"comments":"your channel is good","data":["youTube"],"pod":"library"}
comments|your channel is good
data|["youTube"]
0|youTube
pod|library

由于JSON对象与简单值混合在一起,我们不能再简单地添加where json_extract( value, '$.pod' ) = 'fb',因为当value不代表对象时,这会产生错误。解决此问题的最简单方法是查看type / json_each()返回的json_tree()值:如果该行表示一个JSON对象,则它们将是字符串object(请参见上文)其他值的文档。)

将此内容添加到where子句中(并依靠“短路评估”来防止在非对象行上调用json_extract()),我们得到:

select key, value
  from datatable, json_tree( datatable.data, '$.ALL' )
 where type = 'object'
   and json_extract( value, '$.pod' ) = 'fb' ;

返回:

2|{"comments":"you like everything","data":["facebook"],"pod":"fb"}
1|{"comments":"inserted by TripeHound","data":["facebook"],"pod":"fb"}

如果需要,我们可以使用json_extract()拆分返回的对象:

.mode column
.headers on
.width 30 15 5
select json_extract( value, '$.comments' ) as Comments,
       json_extract( value, '$.data' ) as Data,
       json_extract( value, '$.pod' ) as POD
  from datatable, json_tree( datatable.data, '$.ALL' )
 where type = 'object'
   and json_extract( value, '$.pod' ) = 'fb' ;

Comments                        Data             POD
------------------------------  ---------------  -----
you like everything             ["facebook"]     fb
inserted by TripeHound          ["facebook"]     fb

注意:如果您的结构包含其他对象,它们的格式不同,仅选择type = 'object'可能还不够:您可能必须设计一个更细微的过滤过程。< / p>