PostgreSQL JSONB: сохранить и найти значение
В PostgreSQL тип jsonb хранит JSON в бинарном представлении и поддерживает поиск по ключам и значениям. Оператор ->> возвращает поле как текст, а @> проверяет, содержит ли документ заданный JSON-фрагмент.
Создать JSONB и получить поле
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.
Найти документы по вложенному ключу
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-индекс:
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);Оператор | Результат |
|---|---|
| JSON-значение ключа |
| Текстовое значение |
| Проверка containment |
| Проверка наличия ключа верхнего уровня |
Почему ->> возвращает NULL?
Проверьте, что ключ написан верно и находится на нужном уровне вложенности. Для вложенных объектов соедините операторы, например payload->'user'->>'id'.
Индекс ускорит любой JSONB-запрос?
Нет. Подберите тип и выражение индекса под конкретный оператор и проверьте план через EXPLAIN; GIN увеличивает стоимость записи и размер базы.