Si JSONB c’est un coffre magique où tu ranges tes données, alors || et jsonb_concat() sont les outils qui te permettent de fusionner ces coffres ou de modifier leur contenu. Dans la vraie vie, tu pourrais avoir besoin de fusionner plusieurs objets JSON, d’ajouter des données d’un objet à un autre ou de combiner des tableaux en une seule liste.
Par exemple, imagine que tu as deux objets JSONB :
{"name": "Alice", "age": 25}
et
{"city": "Wonderland", "hobbies": ["reading", "chess"]}
Tu veux obtenir :
{"name": "Alice", "age": 25, "city": "Wonderland", "hobbies": ["reading", "chess"]}
Ou fusionner deux tableaux JSONB :
[1, 2, 3]
et
[4, 5, 6]
pour que le résultat ressemble à :
[1, 2, 3, 4, 5, 6]
Tout ça se fait avec || ou jsonb_concat(). On va voir comment ça marche.
L’opérateur || pour fusionner du JSONB
L’opérateur || permet de fusionner deux objets ou tableaux JSONB dans PostgreSQL. Il est simple, rapide et facile à utiliser. Voici les règles de base :
- Si tu fusionnes deux objets JSONB, l’objet résultat contiendra les clés et valeurs des deux objets.
- Si des clés sont identiques, la valeur de l’opérande de droite remplace celle de gauche.
- Si tu fusionnes des tableaux JSONB, les éléments du tableau de gauche et de droite sont mis bout à bout dans un seul tableau.
Exemple 1 : Fusion de deux objets JSONB
SELECT '{"name": "Alice", "age": 25}'::jsonb || '{"city": "Wonderland", "hobbies": ["reading", "chess"]}'::jsonb AS merged_object;
Résultat :
{"name": "Alice", "age": 25, "city": "Wonderland", "hobbies": ["reading", "chess"]}
Exemple 2 : Mise à jour des valeurs quand les clés sont identiques
SELECT '{"name": "Alice", "age": 25}'::jsonb || '{"age": 30, "city": "Wonderland"}'::jsonb AS updated_object;
Résultat :
{"name": "Alice", "age": 30, "city": "Wonderland"}
Fais gaffe, la valeur de la clé "age" de l’objet de droite a remplacé celle de gauche.
Exemple 3 : Fusion de tableaux
SELECT '[1, 2, 3]'::jsonb || '[4, 5, 6]'::jsonb AS merged_array;
Résultat :
[1, 2, 3, 4, 5, 6]
La fonction jsonb_concat() pour fusionner du JSONB
La fonction jsonb_concat() marche pareil que l’opérateur ||, mais elle est plus flexible si tu veux l’utiliser dans des fonctions, des triggers ou des requêtes dynamiques. Elle prend deux arguments de type JSONB et renvoie le résultat fusionné.
Exemple : utilisation de jsonb_concat()
SELECT jsonb_concat('{"a": 1, "b": 2}'::jsonb, '{"b": 3, "c": 4}'::jsonb) AS combined;
Résultat :
{"a": 1, "b": 3, "c": 4}
Fusion d’objets et de tableaux : subtilités et pièges
Quand tu fusionnes des objets avec des clés identiques, il faut savoir que les valeurs de l’objet de droite sont prioritaires.
Par exemple :
SELECT '{"key1": "value1"}'::jsonb || '{"key1": "value2"}'::jsonb AS result;
Résultat :
{"key1": "value2"}
Si tu veux éviter d’écraser les valeurs, il vaut mieux stocker ces données dans des clés différentes ou utiliser une autre approche (genre un tableau).
Par contre, les tableaux sont toujours fusionnés en ajoutant les éléments du tableau de droite à celui de gauche. Par exemple :
SELECT '["a", "b"]'::jsonb || '["c", "d"]'::jsonb AS result;
Résultat :
["a", "b", "c", "d"]
Si le tableau contient des objets, l’ordre est conservé :
SELECT '[{"id": 1}, {"id": 2}]'::jsonb || '[{"id": 3}]'::jsonb AS result;
Résultat :
[{"id": 1}, {"id": 2}, {"id": 3}]
Exemples pratiques
Mise à jour du profil utilisateur. Imaginons qu’on a une table users où les profils sont stockés en JSONB :
CREATE TABLE users (
id SERIAL PRIMARY KEY,
profile JSONB
);
INSERT INTO users (profile) VALUES ('{"name": "Alice", "age": 25}');
Maintenant, on veut ajouter la ville de résidence :
UPDATE users
SET profile = profile || '{"city": "Wonderland"}'
WHERE id = 1;
Résultat de la requête :
{"name": "Alice", "age": 25, "city": "Wonderland"}
Fusion des infos de commande. Disons qu’on a une table orders :
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
details JSONB
);
INSERT INTO orders (details) VALUES ('{"items": [{"product": "laptop", "quantity": 1}]}');
Maintenant, on ajoute un autre produit à la commande :
UPDATE orders
SET details = jsonb_set(
details,
'{items}',
details->'items' || '[{"product": "mouse", "quantity": 2}]'::jsonb
)
WHERE id = 1;
Résultat de la requête :
{"items": [{"product": "laptop", "quantity": 1}, {"product": "mouse", "quantity": 2}]}
Différences entre || et jsonb_concat()
En pratique, l’opérateur || et la fonction jsonb_concat() font la même chose. Utilise || pour les requêtes simples, c’est plus court à écrire. La fonction jsonb_concat() est pratique quand tu veux l’appeler explicitement dans un programme ou un trigger.
Erreurs fréquentes et comment les éviter
Erreur : tentative de fusionner des types incompatibles.
SELECT '{"key": "value"}'::jsonb || '["value"]'::jsonb;
Résultat :
ERROR: cannot concatenate jsonb objects and arrays
Ici à gauche c’est un objet, à droite un tableau — PostgreSQL ne peut pas les fusionner comme ça. Pour que ça marche, les deux opérandes doivent être du même type : soit deux objets, soit deux tableaux.
Oubli : pas d’index lors de l’utilisation de JSONB
Si tu filtres souvent sur des valeurs à l’intérieur de champs JSONB et que t’as pas d’index — tes requêtes vont ramer sévère. Ce n’est pas une erreur au sens strict, mais ça flingue les perfs. Pense à utiliser les index GIN :
CREATE INDEX idx_profile_data ON employees USING gin(profile);
GO TO FULL VERSION