3

我有一个 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>'));
4

1 回答 1

8

简单列表

你的 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 对象的顶级,则路径可以省略是必须的)。在您的情况下,这将为每个评论条目返回一行。

此行的字段记录在4.13 中。SQLite 文档中的 json_each() 和 json_tree() 表值函数:我们感兴趣的两个是key(非常粗略地,“行号”)和value(当前元素的 JSON)。后者将包含名为commentandpod等的元素。

因为我们只对pod等于的元素感兴趣fb,所以我们添加一个where子句,使用json_extract()to get at pod(where$.pod是相对于函数value返回的json_each)。

嵌套列表

如果您的 JSON 包含嵌套元素(我一开始没有注意到),那么您需要使用该json_tree()函数而不是json_each(). 而后者只会遍历指定节点的直接子节点,json_tree()将递归地遍历指定节点的所有子节点。

为了给我们一些数据,我用一个额外的元素扩充了你的测试数据:

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"
                }]
            }
        ]
    }
'));

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

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 对象,这些将是字符串(有关其他值,请参见上面的文档)。json_each()json_tree()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

注意:如果您的结构包含其他不同格式的对象,那么简单地选择 for 可能是不够的type = 'object':您可能需要设计一个更微妙的过滤过程。

于 2019-10-23T10:58:45.227 回答