PostgreSQL JSONB: сохранить и найти значение

Категория: Postgresql · Язык: SQL · Обновлено:

В PostgreSQL тип jsonb хранит JSON в бинарном представлении и поддерживает поиск по ключам и значениям. Оператор ->> возвращает поле как текст, а @> проверяет, содержит ли документ заданный JSON-фрагмент.

Создать JSONB и получить поле

SQL
CREATE TEMP TABLE events (id int, payload jsonb);
INSERT INTO events VALUES
  (1, '{"type":"login","user":{"id":42}}'),
  (2, '{"type":"purchase","user":{"id":42}}');

SELECT id, payload->>'type' AS event_type,
       payload->'user'->>'id' AS user_id
FROM events
ORDER BY id;

-> сохраняет JSON-тип, ->> возвращает текст. Если путь или ключ отсутствует, выражение вернёт NULL.

Найти документы по вложенному ключу

SQL
WITH events(payload) AS (
  VALUES ('{"type":"login","user":{"id":42}}'::jsonb),
         ('{"type":"purchase","user":{"id":42}}'::jsonb)
)
SELECT payload FROM events
WHERE payload @> '{"user":{"id":42}}';

Для частых containment-поисков можно создать GIN-индекс:

SQL
CREATE TEMP TABLE events (id int, payload jsonb);
INSERT INTO events VALUES (1, '{"type":"login"}');
CREATE INDEX events_payload_gin ON events USING GIN (payload);

Оператор

Результат

payload -> 'user'

JSON-значение ключа

payload ->> 'type'

Текстовое значение

payload @> '{"type":"login"}'

Проверка containment

payload ? 'type'

Проверка наличия ключа верхнего уровня

Почему ->> возвращает NULL?

Проверьте, что ключ написан верно и находится на нужном уровне вложенности. Для вложенных объектов соедините операторы, например payload->'user'->>'id'.

Индекс ускорит любой JSONB-запрос?

Нет. Подберите тип и выражение индекса под конкретный оператор и проверьте план через EXPLAIN; GIN увеличивает стоимость записи и размер базы.