получить значение nodeValue
строк, где key = 'key3' AND key = 'key4'
.
Лучше всего использовать jsonb
оператор "содержит" @>
:
SELECT customerid, customerOrders->'nodeValue'
FROM customer
WHERE customerOrders->'nodeValue' @> '[{"key": "key3"}]'
AND customerOrders->'nodeValue' @> '[{"key": "key4"}]';
Чтобы сделать это быстрый для больших таблиц, поддерживают его с индексом. В идеале индекс jsonb_path_ops
:
CREATE INDEX customer_nodeValue_idx ON customer
USING gin ((customerOrders->'nodeValue') jsonb_path_ops); -- parentheses required
См .:
Более поздняя версия вашего вопроса немного сложнее:
возвращает значение для 'key3' и 'key4'
SELECT c.customerid, o.values
FROM customer c
CROSS JOIN LATERAL (
SELECT ARRAY(
SELECT o.ord->>'value'
FROM jsonb_array_elements(c.customerOrders->'nodeValue') o(ord)
WHERE (o.ord->>'key' = 'key3' OR
o.ord->>'key' = 'key4')
)
) o(values)
WHERE c.customerOrders->'nodeValue' @> '[{"key": "key3"}]'
AND c.customerOrders->'nodeValue' @> '[{"key": "key4"}]';
Первый фильтр квалифицирует строки, как указано выше (с быстрым поиском по индексу). Затем откройте документ JSON и постройте ответ в подзапросе LATERAL
. Должно быть самым простым, чистым и быстрым. О технике см .:
Я добавил customerid
к результат обоих запросов для идентификации строк. Это необязательно.
db <> скрипка здесь (демонстрирует оба)
Дизайн
Вы можете упростить свою раздутую JSON макет примерно такой:
'{
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": "value4",
"key5": "value5"
}'
Или хотя бы:
'[
{
"key1": "value1"
},
{
"key2": "value2"
},
{
"key3": "value3"
},
{
"key4": "value4"
},
{
"key5": "value5"
}
]'
Сделал бы все значительно проще, меньше и быстрее.