CodeGym /Cursos /SQL SELF /Unión y modificación de objetos JSON con el operador || y...

Unión y modificación de objetos JSON con el operador || y la función jsonb_concat()

SQL SELF
Nivel 34 , Lección 0
Disponible

Si JSONB es como un cofre mágico donde metemos datos, entonces || y jsonb_concat() son las herramientas que nos permiten juntar esos cofres o cambiar lo que hay dentro. En la vida real, puede que necesites unir varios objetos JSON, añadir datos de uno a otro o juntar arrays en una sola lista.

Por ejemplo, imagina que tienes dos objetos JSONB:

{"nombre": "Alice", "edad": 25}

y

{"ciudad": "Wonderland", "aficiones": ["leer", "ajedrez"]}

Quieres obtener:

{"nombre": "Alice", "edad": 25, "ciudad": "Wonderland", "aficiones": ["leer", "ajedrez"]}

O unir dos arrays JSONB:

[1, 2, 3]

y

[4, 5, 6]

para que el resultado sea así:

[1, 2, 3, 4, 5, 6]

Todo esto se hace con || o jsonb_concat(). Vamos a ver cómo funciona.

El operador || para unir JSONB

El operador || te deja unir dos objetos o arrays JSONB en PostgreSQL. Es fácil, rápido y directo de usar. Aquí tienes las reglas básicas:

  • Si unes dos objetos JSONB, el resultado tendrá las claves y valores de ambos objetos.
  • Si hay claves repetidas, el valor del operando derecho reemplaza al del izquierdo.
  • Si unes arrays JSONB, los elementos del array izquierdo y derecho se juntan en un solo array.

Ejemplo 1: Unión de dos objetos JSONB

SELECT '{"nombre": "Alice", "edad": 25}'::jsonb || '{"ciudad": "Wonderland", "aficiones": ["leer", "ajedrez"]}'::jsonb AS objeto_unido;

Resultado:

{"nombre": "Alice", "edad": 25, "ciudad": "Wonderland", "aficiones": ["leer", "ajedrez"]}

Ejemplo 2: Actualización de valores cuando las claves coinciden

SELECT '{"nombre": "Alice", "edad": 25}'::jsonb || '{"edad": 30, "ciudad": "Wonderland"}'::jsonb AS objeto_actualizado;

Resultado:

{"nombre": "Alice", "edad": 30, "ciudad": "Wonderland"}

Fíjate que el valor de la clave "edad" del objeto derecho reemplazó al del izquierdo.

Ejemplo 3: Unión de arrays

SELECT '[1, 2, 3]'::jsonb || '[4, 5, 6]'::jsonb AS array_unido;

Resultado:

[1, 2, 3, 4, 5, 6]

La función jsonb_concat() para unir JSONB

La función jsonb_concat() funciona igual que el operador ||, pero te da más flexibilidad si necesitas usarla en funciones, triggers o consultas dinámicas. Recibe dos argumentos tipo JSONB y devuelve el resultado unido.

Ejemplo: usando jsonb_concat()

SELECT jsonb_concat('{"a": 1, "b": 2}'::jsonb, '{"b": 3, "c": 4}'::jsonb) AS combinado;

Resultado:

{"a": 1, "b": 3, "c": 4}

Unión de objetos y arrays: detalles y matices

Cuando unes objetos con claves repetidas, tienes que saber que los valores del objeto derecho tienen prioridad.

Por ejemplo:

SELECT '{"clave1": "valor1"}'::jsonb || '{"clave1": "valor2"}'::jsonb AS resultado;

Resultado:

{"clave1": "valor2"}

Si quieres evitar que se reemplacen valores, deberías guardar esos datos en claves distintas o usar otro enfoque (por ejemplo, un array).

Y los arrays siempre se unen añadiendo los elementos del array derecho al izquierdo. Por ejemplo:

SELECT '["a", "b"]'::jsonb || '["c", "d"]'::jsonb AS resultado;

Resultado:

["a", "b", "c", "d"]

Si dentro del array hay objetos, el orden de los objetos se mantiene:

SELECT '[{"id": 1}, {"id": 2}]'::jsonb || '[{"id": 3}]'::jsonb AS resultado;

Resultado:

[{"id": 1}, {"id": 2}, {"id": 3}]

Ejemplos prácticos

Actualización del perfil de usuario. Supón que tenemos una tabla usuarios donde los perfiles se guardan en formato JSONB:

CREATE TABLE usuarios (
    id SERIAL PRIMARY KEY,
    perfil JSONB
);

INSERT INTO usuarios (perfil) VALUES ('{"nombre": "Alice", "edad": 25}');

Ahora queremos añadir la ciudad de residencia:

UPDATE usuarios 
SET perfil = perfil || '{"ciudad": "Wonderland"}'
WHERE id = 1;

Resultado de la consulta:

{"nombre": "Alice", "edad": 25, "ciudad": "Wonderland"}

Unión de datos de pedidos. Supón que tenemos una tabla pedidos:

CREATE TABLE pedidos (
    id SERIAL PRIMARY KEY,
    detalles JSONB
);

INSERT INTO pedidos (detalles) VALUES ('{"articulos": [{"producto": "portatil", "cantidad": 1}]}');

Ahora añadimos otro producto al pedido:

UPDATE pedidos
SET detalles = jsonb_set(
    detalles,
    '{articulos}',
    detalles->'articulos' || '[{"producto": "raton", "cantidad": 2}]'::jsonb
)
WHERE id = 1;

Resultado de la consulta:

{"articulos": [{"producto": "portatil", "cantidad": 1}, {"producto": "raton", "cantidad": 2}]}

Diferencias entre || y jsonb_concat()

En la práctica, el operador || y la función jsonb_concat() hacen lo mismo. Usa || si escribes consultas simples, porque es más corto. La función jsonb_concat() es útil cuando necesitas llamarla explícitamente dentro de un programa o trigger.

Errores típicos y cómo evitarlos

Error: intentar unir tipos incompatibles.

SELECT '{"clave": "valor"}'::jsonb || '["valor"]'::jsonb;

Resultado:

ERROR:  no se pueden concatenar objetos y arrays jsonb

Aquí a la izquierda hay un objeto y a la derecha un array — PostgreSQL no puede unirlos así sin más. Para que funcione, ambos operandos tienen que ser del mismo tipo: o dos objetos, o dos arrays.

Olvido: no tener índices al trabajar con JSONB

Si filtras mucho por valores dentro de campos JSONB y no tienes índices, las consultas pueden ir lentísimas. No es un error clásico, pero el bajón de rendimiento se nota. No te olvides de usar índices GIN:

CREATE INDEX idx_datos_perfil ON empleados USING gin(perfil);
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION