2016-05-31 2 views
0

У меня есть поле json (хранится как текст) в таблице, и я хочу извлечь определенные элементы из json, у которых есть указанный ID во вложенном массиве (внутри json).Фильтр PostgreSQL на основе идентификатора в вложенном массиве json

Каждый элемент json имеет атрибут type и атрибут value. Кроме того, value имеет атрибут (массив) GRI, который я хотел бы использовать для фильтрации. Вот образец столбцу один streamfield:

[{"type": "paragraph", 
    "value": {"paragraph": "<p>Sample paragraph 91</p>", "GRI": [27, 91, 211]}, 
{"type": "paragraph", 
    "value": {"paragraph": "<p>Sample paragraph 191</p>", "GRI": [13, 191, 271]}] 

Этот запрос вид работ:

SELECT value FROM "sampletable" r, json_array_elements(r.streamfield::json) obj 
WHERE obj->>'type' = 'paragraph' AND obj#>>'{value,GRI}' LIKE '%91%'; 

Это дало бы мне все элементы с ID 91. Но и с ID 191, 291 и т.д .. .

Так как я могу преобразовать оператор `obj # >> '{value, GRI}' в массив, чтобы я мог фильтровать на основе указанного ID?

Вот SQLFiddle для этого: http://sqlfiddle.com/#!15/184e1/1

Edit: выяснены структура JSON

+0

Какая версия PostgreSQL? – Nicarus

+0

Postgres версия 9.3.10 на AWS RDS –

ответ

0

Вот как я бы подойти к этому. В принципе, вам нужно вернуть элементы массива JSON в виде набора, а затем создать из него массив PostgreSQL.

DROP TABLE IF EXISTS "sampletable"; 
CREATE TEMP TABLE "sampletable" (streamfield TEXT); 
INSERT INTO "sampletable" VALUES ('{"type": "paragraph", "value": {"paragraph": "<p>Sample paragraph 91</p>", "GRI": [27, 91, 211]}}'); 

-- Easier to separate out in a CTE, but this could be a subquery, if need be. 
WITH cte AS 
(
    SELECT 
    (streamfield::JSON)->>'type' AS type_text, 
    JSON_EXTRACT_PATH_TEXT(streamfield::JSON,'value','paragraph') AS paragraph_text, 
    (SELECT ARRAY_AGG(col::INT) FROM JSON_ARRAY_ELEMENTS_TEXT(JSON_EXTRACT_PATH(streamfield::JSON,'value','GRI')) tbl(col)) AS gri_array -- This is an INT array now 
    FROM 
    "sampletable" 
) 

SELECT 
    type_text, 
    paragraph_text, 
    gri_array 
FROM 
    cte 
WHERE 
    type_text = 'paragraph' AND 
    91 = ANY(gri_array) 
+0

Это похоже на хороший подход, но вы попробовали его на скрипке? Я получаю сообщение об ошибке: ERROR: функция json_array_elements_text (json) не существует. Подсказка: никакая функция не соответствует указанному имени и типам аргументов. Возможно, вам придется добавлять явные типы. Позиция: 193 –

+0

OK Я отредактировал свой вопрос, чтобы уточнить структуру данных в поле JSON. Каждый столбец streamfield имеет массив json элементов. Не могли бы вы помочь мне найти решение, которое обращается к этой структуре? –

Смежные вопросы