Как правильно извлечь, когда sqlite JSON имеет значение в виде массива - PullRequest
0 голосов
/ 23 октября 2019

У меня есть база данных sqlite, и в одном из полей я сохранил полный объект json. Я должен сделать несколько запросов на выбор JSON. Если вы видите мой json, ключ ALL имеет значение, которое является массивом. Нам нужно извлечь некоторые данные, такие как все комментарии, где поле "pod" имеет значение fb. Как правильно извлечь, когда sqlite json имеет значение в виде массива ?

select json_extract(data, '$. "json"') из datatable;дает мне всю вещь. Затем я выбираю json_extract (data, '$. "Json" [0]'), но я не хочу делать это вручную. Я хочу повторить.

любезно предложите какой-нибудь источник, где я могу учиться и работать над ним. МОЙ ДЖСОН

{
    "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 Ответ

1 голос
/ 23 октября 2019

Простой список

Если ваш 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. Табличные функции json_each () и json_tree () в документации по SQLite: нас интересуют: key (очень приблизительно, "номер строки") и value (JSON длятекущий элемент). Последний будет содержать элементы с именами comment и pod и т. Д.

Поскольку нас интересуют только элементы, в которых pod равен fb, мы добавляем предложение where, используяjson_extract() для получения в pod (где $.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"
                }]
            }
        ]
    }
'));

Если бы мы просто переключились на использование 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_each() / json_tree(): это будет строка object, если строка представляет объект JSON (другие значения см. В документации выше).

Добавляя это к предложению 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': возможно, вам придется разработать более тонкий процесс фильтрации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...