Tipul de date JSONB din PostgreSQL a transformat baza de date relațională într-un motor hibrid document-oriented de mare viteză: spre deosebire de tipul simplu `json` (care păstrează textul brut), `jsonb` stochează datele într-un format binar descompus, permițând căutări și indexări extrem de rapide.
PostgreSQL oferă o suită de operatori nativi de mare putere: operatorul -> (extrage un nod ca JSON), ->> (extrage valoarea ca text brut SQL), și operatorul de contenție @> (verifică dacă un document JSON conține o anumită pereche cheie-valoare).
Pentru colecții cu milioane de rânduri, crearea unui index GIN (Generalized Inverted Index) peste o coloană JSONB permite interogări complexe în câteva milisecunde, eliminând necesitatea de a menține o bază de date separată precum MongoDB.
Sintaxă, opțiuni și concepte cheie
| Opțiune / Concept | Descriere practică |
|---|---|
coloana -> 'cheie' |
Extrage obiectul sau elementul ca JSONB. |
coloana ->> 'cheie' |
Extrage valoarea ca șir text clasic (gata de folosit în clauze WHERE sau ORDER BY). |
coloana @> '{"status": "activ"}' |
Operatorul de contenție ce verifică prezența structurii indicate (utilizează indexul GIN). |
CREATE INDEX ... USING GIN(coloana) |
Indexul inversat ce accelerează interogările de căutare în interiorul JSON-ului. |
Exemple practice și cod
Exemplul 1: Crearea unui tabel de comenzi cu JSONB, index GIN și căutare rapidă
Exemplu complet de utilizare a operatorilor în SQL.
-- 1. Creăm tabelul cu coloană JSONB:
CREATE TABLE comenzi (
id SERIAL PRIMARY KEY,
detalii JSONB NOT NULL
);
-- 2. Creăm indexul GIN pentru căutări ultra-rapide:
CREATE INDEX idx_comenzi_detalii ON comenzi USING GIN (detalii);
-- 3. Inserăm o înregistrare cu structură flexibilă:
INSERT INTO comenzi (detalii) VALUES (
'{"client": "Ion Popescu", "total": 450.50, "status": "platit", "produse": ["tastatura", "mouse"]}'
);
-- 4. Căutare folosind operatorul de contenție @> (utilizează indexul GIN):
SELECT * FROM comenzi WHERE detalii @> '{"status": "platit"}';
-- 5. Extragerea numelui clientului ca text:
SELECT detalii->>'client' AS nume_client, (detalii->>'total')::numeric AS pret FROM comenzi;
Rezultat & Impact
Interogare executată instantaneu pe baza indexului GIN fără scanarea completă a tabelului.
Greșeli frecvente și bune practici
- Utilizarea operatorului `->>` în clauza WHERE fără un index funcțional B-tree, ceea ce declanșează un scan secvențial lent (folosiți operatorul `@>` cu index GIN).
- Folosirea tipului vechi `JSON` în loc de `JSONB`, ceea ce necesită re-parsarea textului la fiecare interogare.