jsonb : des documents dans une base relationnelle
Avancéjsonb stocke du JSON dans un format binaire indexable : idéal pour des attributs variables, des payloads d'événements ou des configurations, sans quitter le modèle relationnel.
CREATE TABLE evenements (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
type text NOT NULL,
donnees jsonb NOT NULL
);
INSERT INTO evenements (type, donnees)
VALUES ('achat', '{"client": {"id": 42, "pays": "FR"}, "articles": [{"sku": "A1", "qte": 2}]}');
Les opérateurs#
| Opérateur | Rôle | Exemple |
|---|---|---|
-> | Extrait un champ (résultat jsonb) | donnees -> 'client' |
->> | Extrait un champ en texte | donnees -> 'client' ->> 'pays' |
#>> | Extrait par chemin, en texte | donnees #>> '{client,id}' |
@> | Contient | donnees @> '{"type": "achat"}' |
? | Une clé existe | donnees ? 'client' |
jsonb_path_exists | Requête JSONPath | jsonb_path_exists(donnees, '$.articles[*] ? (@.qte > 1)') |
SELECT donnees -> 'client' ->> 'pays' AS pays, count(*)
FROM evenements
WHERE donnees @> '{"client": {"pays": "FR"}}'
GROUP BY 1;
-- Modifier un champ
UPDATE evenements SET donnees = jsonb_set(donnees, '{client,pays}', '"BE"') WHERE id = 1;
Indexer#
CREATE INDEX evenements_donnees_gin ON evenements USING gin (donnees); -- @>, ?, etc.
CREATE INDEX evenements_pays_idx ON evenements ((donnees #>> '{client,pays}')); -- un champ précis
jsonb ou colonnes ?#
- Colonnes : données stables, requêtées, jointes, contraintes (clés étrangères,
NOT NULL, types). jsonb: attributs variables ou peu utilisés pour filtrer, données reçues d'un tiers à conserver telles quelles.
Piège : un
jsonb« fourre-tout » perd les garanties du relationnel : pas de clé étrangère, pas de type imposé, statistiques du planificateur limitées. Extrayez en colonnes les champs dont vous filtrez, joignez ou triez souvent (éventuellement en colonne générée).