Ce face JSONB și operatorii ->, ->>, @>, ?
PostgreSQL oferă două tipuri pentru stocarea documentelor JSON: json (care păstrează textul brut exact cum a fost primit) și jsonb (care descompune documentul într-un format binar optimizat, elimină spațiile inutile, ordonează cheile și suportă indexare GIN). În aproape toate aplicațiile se recomandă folosirea tipului JSONB.
Pentru navigarea în obiecte și vectori JSONB se folosesc operatorii -> (returnează tot un element jsonb, util pentru înlănțuire) și ->> (returnează valoarea ca text, utilă pentru afișare sau conversie la număr). Pentru filtrări rapide în clauza WHERE asistate de un index GIN, se folosesc operatorul de incluziune @> și operatorul de existență a cheii ?.
Clauze, operatori și argumente
| Clauză / Operator | Descriere |
|---|---|
jsonb -> 'cheie' (sau -> index) |
Extrage câmpul obiectului sau elementul din array (de la 0) păstrând tipul de date jsonb (cu ghilimele pentru șiruri). |
jsonb ->> 'cheie' (sau ->> index) |
Extrage câmpul obiectului sau elementul din array direct ca text (fără ghilimele JSON). |
jsonb #> '{cale,subcale}' |
Extrage sub-obiectul jsonb aflat la calea specificată (sau ca text cu #>>). |
jsonb @> '{"k": "v"}'::jsonb |
Operatorul de incluziune (contains): verifică dacă documentul din stânga conține structura JSONB din dreapta (indexabil GIN). |
jsonb ? 'cheie' |
Verifică dacă șirul apare ca nume de cheie la nivelul curent (sau ca element într-un array JSONB). |
jsonb ?| array / ?& array |
Verifică dacă există oricare (?|) sau toate (?&) cheile din tabloul de text specificat. |
Exemple
Exemplul 1: Extragerea câmpurilor și filtrarea cu operatorul de incluziune @>
Selectăm produsele care au în coloana specificatii (de tip jsonb) atributul "memorie_ram": 32 și extragem procesorul ca text cu ->>.
SELECT id,
denumire,
specificatii->>'procesor' AS procesor,
(specificatii->>'greutate_kg')::numeric AS greutate_kg
FROM produse
WHERE specificatii @> '{"memorie_ram": 32, "stocare": {"tip": "NVMe"}}'::jsonb;
Rezultat interogare
id | denumire | procesor | greutate_kg
----+---------------------+--------------+-------------
12 | ProBook Ultra 16 M3 | Apple M3 Pro | 1.62
19 | ThinkStation Dev 15 | Ryzen 9 7940 | 1.85
(2 rows)
Exemplul 2: Verificarea existenței unei chei și accesul prin subscripție nativă (PostgreSQL 14+)
Filtrăm utilizatorii care au cheia telefon_urgenta definită în profilul JSONB și citim orașul din sub-obiectul adresa.
SELECT id,
email,
profil['adresa']['oras'] #>> '{}' AS oras,
profil->>'telefon_urgenta' AS telefon_urgenta
FROM utilizatori
WHERE profil ? 'telefon_urgenta';
Rezultat interogare
id | email | oras | telefon_urgenta
----+-------------------------+-----------+-----------------
14 | andrei.popescu@firma.ro | București | +40722111222
29 | elena.pm@exemplu.ro | Cluj | +40744333444
(2 rows)
Greșeli frecvente
- Compararea cu un șir sau conversia la număr folosind
->în loc de->>: expresiaspecificatii->'procesor'returnează unjsonbcu ghilimele incluse ("Apple M3 Pro"), în timp ce->>returnează textul curat. - Filtrarea prin
WHERE specificatii->>'memorie_ram' = '32'nu folosește un index GIN standard pe întreaga coloanăspecificatii; rescrie condiția caWHERE specificatii @> '{"memorie_ram": 32}'pentru a beneficia de indexul GIN.
Comenzi și funcții înrudite
jsonb_build_object, jsonb_agg și jsonb_set: Construiește obiecte și vectori JSONB din rânduri relaționale și modifică parțial documente JSONB existente.CREATE INDEX (B-Tree, GIN, Partial, CONCURRENTLY): Creează indecși B-Tree, GIN (pentru JSONB și Array), indecși parțiali (WHERE) și indecși pe expresii fără blocarea scrierilor.ARRAY, ANY() și unnest(): Stochează și manipulează tablouri tipizate (text[], int[]), verifică apartenența cu ANY() și le extinde în rânduri cu unnest().