Ваши регулярно структурированные данные будут чище, меньше и быстрее, чем нормализованный реляционный дизайн.
Тем не менее, чтобы сделать вашу настройку намного более быстрой (если не так быстро, как нормализованный дизайн с соответствующими индексами), добавьте индекс GIN в выражение data->'friends'
:
CREATE INDEX tbl_data_friends_gin_idx ON tbl USING gin ((data->'friends'));
Затем добавьте соответствующее предложение WHERE
к нашему запросу с оператором содержимого @>
:
SELECT DISTINCT -- why DISTINCT ?
id, data->>'_id' AS json_id, data->>'email' AS email
, friends->>'name' AS friend_name, parent->>'name' AS parent
FROM tbl t
CROSS JOIN jsonb_array_elements(t.data->'friends') friends
CROSS JOIN jsonb_array_elements(friends->'parent') parent
<b>WHERE t.data->'friends' @> '[{"name": "Chan Franco", "parent": [{"name": "Hannah Golden"}]}]'</b>
AND friends->>'name' = 'Chan Franco'
AND parent ->>'name' = 'Hannah Golden';
дБ <> скрипка здесь
огромная разница: с помощью индекса Postgres теперь может идентифицировать совпадающие строки до , отменяя каждый вложенный массив "друзей" в весь стол Только после того, как идентифицирует совпадающие строки в базовой таблице, вызывается jsonb_array_elements()
, и результирующие строки с соответствующими элементами массива сохраняются.
Обратите внимание, что поисковое выражение должно быть допустимым JSON, соответствующим структуре массива JSON data->'friends'
, включая внешние скобки []
. Но пропустите все пары ключ / значение, которые не должны служить фильтром.
Связанный:
Я избегал названия таблицы temp
, так как это ключевое слово SQL, которое может привести к ошибочным ошибкам. Вместо этого используйте имя tbl
.