Gymterview
middle

Какие операторы существуют для работы с JSONB?

PostgreSQL предоставляет три группы операторов для JSONB: извлечение данных, проверка вхождения и модификация. Это позволяет работать с JSON-данными без извлечения их в приложение.

Операторы извлечения данных

Оператор Описание Пример Результат
-> Получить элемент по ключу (JSON) '{"a":1}'::jsonb -> 'a' 1 (jsonb)
->> Получить элемент по ключу (текст) '{"a":1}'::jsonb ->> 'a' 1 (text)
#> Получить по пути (JSON) '{"a":{"b":2}}'::jsonb #> '{a,b}' 2 (jsonb)
#>> Получить по пути (текст) '{"a":{"b":2}}'::jsonb #>> '{a,b}' 2 (text)

Операторы проверки

Оператор Описание Пример
@> Левое содержит правое '{"a":1,"b":2}'::jsonb @> '{"a":1}'
<@ Левое содержится в правом '{"a":1}'::jsonb <@ '{"a":1,"b":2}'
? Содержит ключ '{"a":1}'::jsonb ? 'a'
`? ` Содержит хотя бы один ключ
?& Содержит все ключи '{"a":1,"b":2}'::jsonb ?& array['a','b']

Операторы модификации

Оператор Описание Пример
` `
- Удаление ключа '{"a":1,"b":2}'::jsonb - 'a'
#- Удаление по пути '{"a":{"b":1}}'::jsonb #- '{a,b}'
Практические примеры
-- Найти клиентов с определённой настройкой
SELECT client_id
FROM client_settings
WHERE settings @> '{"theme": "dark"}';

-- Получить значение вложенного ключа
SELECT settings -> 'notifications' ->> 'email' AS email_enabled
FROM client_settings
WHERE client_id = 1;

-- Обновить отдельный ключ через jsonb_set
UPDATE client_settings
SET settings = jsonb_set(settings, '{theme}', '"light"')
WHERE client_id = 1;

-- Добавить новый ключ
UPDATE client_settings
SET settings = settings || '{"language": "ru"}'::jsonb
WHERE client_id = 1;

-- Полезные функции
SELECT jsonb_pretty(settings) FROM client_settings;     -- красивый вывод
SELECT jsonb_each(settings) FROM client_settings;       -- разбор на key-value
SELECT jsonb_object_keys(settings) FROM client_settings; -- только ключи
SELECT jsonb_array_elements('[1,2,3]'::jsonb);           -- разбор массива

На собеседовании: ключевое различие -> и ->>: первый возвращает jsonb (для дальнейшей навигации), второй — text (для сравнений и вывода). Для индексированного поиска используйте @> с GIN-индексом, а не ->>с B-tree.