Trabajar con datos JSON en PostgreSQL es una herramienta potente, pero como cualquier herramienta, hay que usarla con cabeza. Incluso un pequeño fallo puede convertir tu consulta en un auténtico rompecabezas. Hoy vamos a centrarnos otra vez en los errores más típicos que aparecen al trabajar con JSON y JSONB en PostgreSQL, y en cómo puedes evitarlos.
Problema 1: usar JSON en vez de JSONB
Mucha gente que empieza usa el tipo de dato JSON pensando que es la mejor opción para guardar datos en formato JSON. Pero JSON en PostgreSQL guarda los datos como texto, lo que puede hacer que las búsquedas o filtros sean mucho más lentos.
Ejemplo de error:
CREATE TABLE products (
id SERIAL PRIMARY KEY,
details JSON
);
INSERT INTO products (details) VALUES ('{"name": "Laptop", "price": 1000}');
INSERT INTO products (details) VALUES ('{"name": "Laptop", "price": 1000}');
Si intentas filtrar por la clave (price), verás que va mucho más lento que si usas JSONB.
Cómo arreglarlo: usa JSONB si tienes pensado filtrar mucho o acceder a los datos a menudo.
CREATE TABLE products (
id SERIAL PRIMARY KEY,
details JSONB
);
Problema 2: no crear índices para JSONB
JSONB es una pasada de potente, pero si no pones índices, las consultas complejas pueden ir bastante lentas.
Ejemplo de error: imagina que tienes una tabla con la columna details donde guardas un montón de objetos JSON:
SELECT * FROM products WHERE details->>'name' = 'Laptop';
Si los datos no están indexados, el servidor hará un escaneo completo de la tabla (full table scan), gastando mucho más tiempo.
Cómo arreglarlo: crea un índice GIN para acelerar la búsqueda por claves:
CREATE INDEX idx_details_name ON products USING gin (details jsonb_path_ops);
Problema 3: errores al extraer datos anidados
Sacar datos de objetos o arrays anidados puede ser un lío, sobre todo si no tienes clara la diferencia entre los operadores -> y ->>.
Ejemplo de error:
SELECT details->'price' FROM products;
Esta consulta te devuelve el valor en formato JSON, no como string ("1000" en vez de 1000). Si quieres el valor tal cual, tienes que usar ->>:
SELECT details->>'price' FROM products;
Problema 4: Uso incorrecto de los operadores
Puede que hayas visto el operador @> y pienses: "¡Suena guay, lo uso siempre!" Pero si no sabes cómo funciona, puedes llevarte sorpresas.
Ejemplo de error:
SELECT * FROM products WHERE details @> '{"price": 1000}';
Esta consulta solo funciona si price es un número en el JSON. Si el valor está guardado como string "1000", la consulta no devuelve nada.
Cómo arreglarlo: fíjate bien en los tipos de datos dentro del JSON:
SELECT * FROM products WHERE details->>'price' = '1000';
Problema 5: Objetos JSON grandes
Guardar objetos JSON muy grandes sin optimizar puede hacer que las consultas vayan lentísimas. Además, leer o modificar incluso una parte pequeña de los datos dentro de un JSONB requiere procesar todo el objeto.
Cómo arreglarlo: si hay claves que usas mucho, sácalas a columnas separadas en la tabla. Por ejemplo:
ALTER TABLE products ADD COLUMN price NUMERIC;
UPDATE products SET price = (details->>'price')::NUMERIC;
Ahora puedes filtrar y ordenar los datos de forma eficiente sin tener que parsear el JSONB.
Problema 6: reconstrucción completa de objetos al modificarlos
Cuando usas funciones como jsonb_set() o jsonb_insert(), PostgreSQL crea un objeto JSONB completamente nuevo, lo que puede ser caro en rendimiento.
Cómo arreglarlo: minimiza el número de actualizaciones sobre JSONB. Por ejemplo, en vez de actualizar un objeto muchas veces, junta todos los cambios en una sola consulta:
UPDATE products
SET details = jsonb_set(details, '{price}', '1500'::jsonb);
Problema 7: no entender la estructura de los arrays
En JSONB los arrays también hay que tratarlos con cuidado. Imagina que tienes un array así:
{
"tags": ["electronics", "laptop", "sale"]
}
Quieres comprobar si existe el tag "laptop". Si usas mal el operador @>, puede que no te devuelva nada, porque espera un array, no un string.
Ejemplo de error:
SELECT * FROM products WHERE details->'tags' @> '"laptop"';
Cómo arreglarlo: Usa el formato correcto en el operador @>:
SELECT * FROM products WHERE details->'tags' @> '["laptop"]';
Recomendaciones para evitar errores
Para no meterte en líos al trabajar con JSONB, sigue estos consejos:
Elige el tipo de dato correcto. Si trabajas con muchos datos y filtras a menudo, usa siempre JSONB en vez de JSON.
Ponle índices a los datos. Si tus consultas van mucho a ciertas claves, crea un índice adecuado (por ejemplo, GIN).
Valida los datos antes de insertarlos. Usa funciones de validación para comprobar la estructura de los datos:
DO $$
BEGIN
IF jsonb_typeof('{"price": 1000}'::jsonb->'price') IS DISTINCT FROM 'number' THEN
RAISE EXCEPTION 'El precio tiene que ser un número';
END IF;
END $$;
Optimiza la estructura de los datos. Si hay claves que usas más que otras, sácalas a columnas separadas en la tabla.
Aprende los operadores y funciones. Lee bien la documentación oficial de PostgreSQL para entender las diferencias entre ->, ->>, @>, ?| y otras funciones.
JSON y JSONB pueden ser tus aliados para trabajar con datos flexibles y complejos. Lo importante es elegir bien las herramientas y evitar los errores típicos, así tu código será eficiente y fácil de mantener.
GO TO FULL VERSION