jsonb_build_object, jsonb_agg și jsonb_set în PostgreSQL

JSONB, Array și tipuri avansate PostgreSQL 9.5+ (standard în PostgreSQL 15–17)

Construiește obiecte și vectori JSONB din rânduri relaționale și modifică parțial documente JSONB existente.

Sintaxă SQL
jsonb_build_object('cheie', col);njsonb_agg(expresie ORDER BY col);njsonb_set(tinta, '{cale,cheie}', valoare_noua_jsonb, true);

Ce face jsonb_build_object, jsonb_agg și jsonb_set

Pe lângă interogarea documentelor JSONB, PostgreSQL oferă funcții puternice pentru generarea de răspunsuri JSON direct din baza de date (jsonb_build_object, to_jsonb, jsonb_agg) și pentru modificarea parțială a câmpurilor dintr-o coloană JSONB fără a rescrie tot documentul din aplicație (jsonb_set și operatorul de concatenare || sau ștergere -).

Combinând jsonb_build_object() cu funcția de agregare jsonb_agg(), poți transforma o relație părinte-copil (ex: o comandă cu toate liniile ei de produse) într-un singur obiect JSON ierarhic gata de trimis către un API REST.

Clauze, operatori și argumente

Clauză / Operator Descriere
jsonb_build_object(k1, v1, k2, v2, ...) Construiește un obiect JSONB din perechi alternante de cheie și valoare.
jsonb_agg(expresie [ORDER BY ...]) Funcție de agregare care adună valorile dintr-un grup într-un array JSONB.
jsonb_set(tinta, cale, val_jsonb [, create]) Înlocuiește sau adaugă (dacă create = true, implicit) valoarea de la cale (ex: '{adresa,oras}').
jsonb1 || jsonb2 Concatenează două obiecte JSONB la nivelul rădăcină (cheile din dreapta suprascriu cheile din stânga).
jsonb - 'cheie' / #- '{cale,cheie}' Șterge o cheie de la nivelul rădăcină (-) sau de la o cale imbricată (#-).
jsonb_array_elements(array_jsonb) Despachetează un array JSONB într-un set de rânduri (câte un rând pentru fiecare element).

Exemple

Exemplul 1: Generarea unui obiect JSON ierarhic (comandă + linii) cu jsonb_build_object și jsonb_agg

Agregăm liniile fiecărei comenzi într-un array JSONB ordonat, gata de serializare în API.

SELECT c.id AS comanda_id,
       jsonb_build_object(
           'comanda_id', c.id,
           'client', cl.nume,
           'total_lei', c.total_lei,
           'articole', COALESCE(
               jsonb_agg(
                   jsonb_build_object(
                       'sku', lc.sku,
                       'cantitate', lc.cantitate,
                       'pret', lc.pret_unitar
                   ) ORDER BY lc.id
               ) FILTER (WHERE lc.id IS NOT NULL),
               '[]'::jsonb
           )
       ) AS payload_json
FROM comenzi c
JOIN clienti cl ON cl.id = c.client_id
LEFT JOIN linii_comanda lc ON lc.comanda_id = c.id
WHERE c.id = 5042
GROUP BY c.id, cl.nume;

Rezultat interogare

 comanda_id |                                                   payload_json                                                    
------------+-------------------------------------------------------------------------------------------------------------------
       5042 | {"client": "Ana Marinescu", "articole": [{"sku": "SSD-1TB", "pret": 420.50, "cantitate": 1}], "total_lei": 420.50, "comanda_id": 5042}
(1 row)

Exemplul 2: Actualizarea unei chei imbricate cu jsonb_set și ștergerea unei chei vechi cu –

Actualizăm rezoluția din sub-obiectul ecran și ștergem simultan cheia învechită cod_intern.

UPDATE produse
SET specificatii = jsonb_set(
        specificatii - 'cod_intern',
        '{ecran,rezolutie}',
        '"3840x2160"'::jsonb,
        true
    )
WHERE id = 41
RETURNING id, specificatii;

Rezultat interogare

 id |                        specificatii                         
----+-------------------------------------------------------------
 41 | {"ecran": {"diagonala": 27, "rezolutie": "3840x2160"}, "rata_hz": 144}
(1 row)

UPDATE 1

Greșeli frecvente

  • La jsonb_set(tinta, '{a,b}', val), dacă obiectul părinte a nu există deloc în tinta, funcția nu va crea automat a și va lăsa documentul neschimbat.
  • Dacă oricare element din jsonb_set este NULL SQL (nu 'null'::jsonb), întreaga funcție returnează NULL (deoarece este definită ca STRICT) și poate șterge accidental toată coloana dacă nu folosești to_jsonb() sau COALESCE.

Comenzi și funcții înrudite

  • JSONB și operatorii ->, ->>, @>, ?: Interoghează și filtrează documente binare JSONB folosind operatorii de extracție (->, ->>) și incluziune (@>, ?).
  • GROUP BY, HAVING și clauza FILTER: Grupează rândurile pentru agregări și aplică condiții individuale pe fiecare funcție agregată prin FILTER (WHERE …).
  • ARRAY, ANY() și unnest(): Stochează și manipulează tablouri tipizate (text[], int[]), verifică apartenența cu ANY() și le extinde în rânduri cu unnest().