Подтвердить что ты не робот

Запрос элементов массива внутри типа JSON

Я пытаюсь проверить тип json в PostgreSQL 9.3.
У меня есть столбец json с именем data в таблице с именем reports. JSON выглядит примерно так:

{
  "objects": [
    {"src":"foo.png"},
    {"src":"bar.png"}
  ],
  "background":"background.png"
}

Я хотел бы запросить таблицу для всех отчетов, которые соответствуют значению 'src' в массиве 'objects'. Например, можно ли запросить в БД все отчеты, соответствующие 'src' = 'foo.png'? Я успешно написал запрос, который может соответствовать "background":

SELECT data AS data FROM reports where data->>'background' = 'background.png'

Но так как "objects" имеет массив значений, я не могу написать что-то, что работает. Можно ли запросить в БД все отчеты, соответствующие 'src' = 'foo.png'? Я просмотрел эти источники, но до сих пор не могу понять:

Я также пробовал подобные вещи, но безрезультатно:

SELECT json_array_elements(data->'objects') AS data from reports
WHERE  data->>'src' = 'foo.png';

Я не эксперт по SQL, поэтому я не знаю, что я делаю неправильно.

4b9b3361

Ответ 1

json в Postgres 9.3 +

Уничтожьте массив JSON с помощью функции json_array_elements() в боковом соединении в предложении FROM и протестируйте его элементы:

WITH reports(data) AS (
   VALUES ('{"objects":[{"src":"foo.png"}, {"src":"bar.png"}]
           , "background":"background.png"}'::json)
   ) 
SELECT *
FROM   reports r, json_array_elements(r.data#>'{objects}') obj
WHERE  obj->>'src' = 'foo.png';

CTE (WITH query) просто заменяет таблицу reports.
Или, эквивалентно только для одного уровня вложенности:

SELECT *
FROM   reports r, json_array_elements(r.data->'objects') obj
WHERE  obj->>'src' = 'foo.png';

->>, -> и #> описаны в руководстве.

Оба запроса используют неявный JOIN LATERAL.

SQL Fiddle.

Близкий ответ:

jsonb в Postgres 9.4 +

Используйте эквивалентный jsonb_array_elements().

Лучше, используйте новый оператор "содержит" @> (лучше всего в сочетании с соответствующим индексом GIN в выражении data->'objects'):

CREATE INDEX reports_data_gin_idx ON reports
USING gin ((data->'objects') jsonb_path_ops);

SELECT * FROM reports WHERE data->'objects' @> '[{"src":"foo.png"}]';

Так как ключ objects содержит массив JSON, нам нужно сопоставить структуру в терминах поиска и обернуть элемент массива в квадратные скобки. Оставьте скобки массива при поиске простой записи.

Подробное объяснение и дополнительные параметры:

Ответ 2

Создайте таблицу со столбцом типа json

# CREATE TABLE friends ( id serial primary key, data jsonb);

Теперь давайте вставим данные JSON

# INSERT INTO friends(data) VALUES ('{"name": "Arya", "work": ["Improvements", "Office"], "available": true}');

# INSERT INTO friends(data) VALUES ('{"name": "Tim Cook", "work": ["Cook", "ceo", "Play"], "uses": ["baseball", "laptop"], "available": false}');

Теперь давайте сделаем несколько запросов для извлечения данных

# select data->'name' from friends;

# select data->'name' as name, data->'work' as work from friends;

Возможно, вы заметили, что результаты поставляются с кавычками (") и скобками ([])

    name    |            work            
------------+----------------------------
 "Arya"     | ["Improvements", "Office"]
 "Tim Cook" | ["Cook", "ceo", "Play"]
(2 rows)

Теперь для извлечения только значений просто используйте ->>

# select data->>'name' as name, data->'work'->>0 as work from friends;

#select data->>'name' as name, data->'work'->>0 as work from friends where data->>'name'='Arya';

Ответ 3

выберите data-> 'objects' → 0-> 'src' как SRC из таблицы, где data-> 'objects' → 0-> 'src' = 'foo.png'