Se JSONB é tipo um baú mágico onde a gente joga os dados, então || e jsonb_concat() são as ferramentas pra juntar esses baús ou mexer no que tem dentro deles. Na vida real, pode rolar de precisar juntar vários objetos JSON, adicionar dados de um em outro ou unir arrays numa lista só.
Por exemplo, imagina que tu tem dois objetos JSONB:
{"name": "Alice", "age": 25}
e
{"city": "Wonderland", "hobbies": ["reading", "chess"]}
Tu quer chegar nisso aqui:
{"name": "Alice", "age": 25, "city": "Wonderland", "hobbies": ["reading", "chess"]}
Ou juntar dois arrays JSONB:
[1, 2, 3]
e
[4, 5, 6]
pra que o resultado fique assim:
[1, 2, 3, 4, 5, 6]
Tudo isso rola usando || ou jsonb_concat(). Bora ver como funciona.
Operador || pra juntar JSONB
O operador || deixa tu juntar dois objetos ou arrays JSONB no PostgreSQL. É simples, rápido e fácil de usar. Olha as regras principais:
- Se tu junta dois objetos JSONB, o resultado vai ter as chaves e valores dos dois.
- Se as chaves batem, o valor do operando da direita substitui o da esquerda.
- Se tu junta arrays JSONB, os elementos dos dois arrays viram um array só.
Exemplo 1: Juntando dois objetos JSONB
SELECT '{"name": "Alice", "age": 25}'::jsonb || '{"city": "Wonderland", "hobbies": ["reading", "chess"]}'::jsonb AS merged_object;
Resultado:
{"name": "Alice", "age": 25, "city": "Wonderland", "hobbies": ["reading", "chess"]}
Exemplo 2: Atualizando valores quando as chaves são iguais
SELECT '{"name": "Alice", "age": 25}'::jsonb || '{"age": 30, "city": "Wonderland"}'::jsonb AS updated_object;
Resultado:
{"name": "Alice", "age": 30, "city": "Wonderland"}
Repara que o valor da chave "age" do objeto da direita substituiu o da esquerda.
Exemplo 3: Juntando arrays
SELECT '[1, 2, 3]'::jsonb || '[4, 5, 6]'::jsonb AS merged_array;
Resultado:
[1, 2, 3, 4, 5, 6]
Função jsonb_concat() pra juntar JSONB
A função jsonb_concat() faz basicamente o mesmo que o operador ||, mas é mais flexível se tu precisa usar ela em funções, triggers ou consultas dinâmicas. Ela recebe dois argumentos do tipo JSONB e devolve o resultado juntado.
Exemplo: usando jsonb_concat()
SELECT jsonb_concat('{"a": 1, "b": 2}'::jsonb, '{"b": 3, "c": 4}'::jsonb) AS combined;
Resultado:
{"a": 1, "b": 3, "c": 4}
Juntando objetos e arrays: detalhes e pegadinhas
Quando tu junta objetos com chaves iguais, lembra que os valores do objeto da direita têm prioridade.
Tipo assim:
SELECT '{"key1": "value1"}'::jsonb || '{"key1": "value2"}'::jsonb AS result;
Resultado:
{"key1": "value2"}
Se tu não quiser que um valor substitua o outro, guarda esses dados em chaves diferentes ou usa outro esquema (tipo array).
Agora, arrays sempre são juntados adicionando os elementos do array da direita no da esquerda. Por exemplo:
SELECT '["a", "b"]'::jsonb || '["c", "d"]'::jsonb AS result;
Resultado:
["a", "b", "c", "d"]
Se dentro do array tem objetos, a ordem dos objetos é mantida:
SELECT '[{"id": 1}, {"id": 2}]'::jsonb || '[{"id": 3}]'::jsonb AS result;
Resultado:
[{"id": 1}, {"id": 2}, {"id": 3}]
Exemplos práticos
Atualizando o perfil do usuário. Imagina que a gente tem uma tabela users, onde os perfis ficam em JSONB:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
profile JSONB
);
INSERT INTO users (profile) VALUES ('{"name": "Alice", "age": 25}');
Agora queremos adicionar a cidade onde mora:
UPDATE users
SET profile = profile || '{"city": "Wonderland"}'
WHERE id = 1;
Resultado da consulta:
{"name": "Alice", "age": 25, "city": "Wonderland"}
Juntando dados de pedidos. Digamos que temos uma tabela orders:
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
details JSONB
);
INSERT INTO orders (details) VALUES ('{"items": [{"product": "laptop", "quantity": 1}]}');
Agora vamos adicionar mais um produto no pedido:
UPDATE orders
SET details = jsonb_set(
details,
'{items}',
details->'items' || '[{"product": "mouse", "quantity": 2}]'::jsonb
)
WHERE id = 1;
Resultado da consulta:
{"items": [{"product": "laptop", "quantity": 1}, {"product": "mouse", "quantity": 2}]}
Diferenças entre || e jsonb_concat()
Na prática, o operador || e a função jsonb_concat() fazem a mesma coisa. Usa || pra consultas simples, porque é mais curto de escrever. A função jsonb_concat() é massa quando tu precisa chamar ela dentro de código ou trigger.
Erros comuns e como evitar
Erro: tentar juntar tipos incompatíveis.
SELECT '{"key": "value"}'::jsonb || '["value"]'::jsonb;
Resultado:
ERROR: cannot concatenate jsonb objects and arrays
Aqui à esquerda tem um objeto e à direita um array — o PostgreSQL não consegue juntar assim. Pra funcionar, os dois lados têm que ser do mesmo tipo: ou dois objetos, ou dois arrays.
Vacilo: não criar índices quando trabalha com JSONB
Se tu filtra muito por valores dentro de campos JSONB e não tem índice — as consultas vão ficar bem lentas. Não é erro clássico, mas o desempenho vai pro saco. Não esquece de usar índices GIN:
CREATE INDEX idx_profile_data ON employees USING gin(profile);
GO TO FULL VERSION