jsonb_object_keys es una funcion que devuelve un conjunto: emite una fila por cada clave de nivel superior de un objeto JSON. Resulta indispensable cuando los datos son semiestructurados y no sabes de antemano que campos hay en una columna. Con ella puedes explorar la forma del JSON, comprobar si los campos esperados estan presentes y construir un inventario de claves de toda una tabla.
Sintaxis y ejemplo basico
La firma es sencilla: jsonb_object_keys(jsonb). Como devuelve un conjunto, produce filas en lugar de un solo escalar. Supon que users ha ganado una columna prefs jsonb con los ajustes del perfil.
SELECT jsonb_object_keys(prefs) AS key
FROM users
WHERE id = 42;
Si prefs es {"theme": "dark", "lang": "en", "newsletter": true}, la consulta devuelve tres filas: theme, lang, newsletter. Algunos comportamientos que conviene conocer:
- Solo se devuelven las claves de nivel superior. Los objetos anidados no se despliegan.
- El orden de las claves no esta garantizado;
jsonb mantiene su propio orden interno.
- Para algo que no sea un objeto (array, numero, cadena) obtienes cero filas o un error; pasale solo objetos.
- Existe la variante
json_object_keys para el tipo json; mismo comportamiento, sin normalizacion.
Cuando una columna jsonb llega de una fuente externa, la primera pregunta es "que claves aparecen aqui". Desplegar las claves de cada fila y agruparlas te da un mapa de campos con sus frecuencias.
SELECT key, COUNT(*) AS rows_with_key
FROM users u,
jsonb_object_keys(u.prefs) AS key
GROUP BY key
ORDER BY rows_with_key DESC;
Este es el patron canonico: una tabla y una funcion de conjunto en el FROM forman un join LATERAL implicito, de modo que las claves de cada usuario se expanden en filas separadas. El resultado muestra al instante que campos son comunes y cuales son opcionales y raros.
Trampa: si prefs es NULL, la fila de ese usuario simplemente desaparece del resultado, porque la funcion no emite ninguna fila. Para conservar a esos usuarios, usa un LEFT JOIN LATERAL ... ON true explicito, o filtra WHERE prefs IS NOT NULL de forma consciente. De lo contrario tu sondeo se salta en silencio parte de la tabla.
Comprobar que campos opcionales estan presentes
jsonb_object_keys ayuda a encontrar filas que llevan (o no) un campo concreto. Para una sola comprobacion el operador ? es mas comodo, pero recorrer las claves sirve para condiciones dinamicas.
SELECT id, email
FROM users
WHERE prefs ? 'newsletter';
SELECT id, email
FROM users u
WHERE EXISTS (
SELECT 1
FROM jsonb_object_keys(u.prefs) AS key
WHERE key = 'newsletter'
);
El operador ? (contiene una clave de nivel superior) casi siempre es mas rapido y claro para un campo, sobre todo con un indice GIN en prefs. Recorrer con jsonb_object_keys se justifica cuando la condicion sobre la clave no es trivial, por ejemplo "tiene al menos una clave con prefijo flag_".
Reunir claves con array_agg
A menudo quieres lo contrario de un despliegue: una lista compacta de claves por fila. Combinar array_agg con una subconsulta sobre jsonb_object_keys pliega las claves de vuelta en un array.
SELECT
u.id,
u.email,
(
SELECT array_agg(key ORDER BY key)
FROM jsonb_object_keys(u.prefs) AS key
) AS configured_keys
FROM users u
WHERE u.prefs IS NOT NULL;
El ORDER BY key dentro de array_agg da un orden estable y legible en lugar del interno de jsonb. Ese array es facil de comparar entre filas: encuentra usuarios con un conjunto de ajustes inusual, o construye un informe de "quien tiene que campos rellenos" sin volcar todo el JSON a la aplicacion.
Otras bases de datos
MySQL no tiene un equivalente directo que devuelva un conjunto: JSON_KEYS(prefs) devuelve un array JSON de claves como un solo valor, no un conjunto de filas. Para desplegarlo recurres a JSON_TABLE. En ClickHouse, el analisis de JSON usa JSONExtractKeys(prefs), que tambien produce un array; expandelo en filas con arrayJoin. Recuerda la regla comun: en los tres sistemas se trata solo de claves de nivel superior, asi que los objetos anidados se analizan en una pasada aparte.
jsonb_object_keyses una funcion que devuelve un conjunto: emite una fila por cada clave de nivel superior de un objeto JSON. Resulta indispensable cuando los datos son semiestructurados y no sabes de antemano que campos hay en una columna. Con ella puedes explorar la forma del JSON, comprobar si los campos esperados estan presentes y construir un inventario de claves de toda una tabla.Sintaxis y ejemplo basico
La firma es sencilla:
jsonb_object_keys(jsonb). Como devuelve un conjunto, produce filas en lugar de un solo escalar. Supon queusersha ganado una columnaprefs jsonbcon los ajustes del perfil.SELECT jsonb_object_keys(prefs) AS key FROM users WHERE id = 42;Si
prefses{"theme": "dark", "lang": "en", "newsletter": true}, la consulta devuelve tres filas:theme,lang,newsletter. Algunos comportamientos que conviene conocer:jsonbmantiene su propio orden interno.json_object_keyspara el tipojson; mismo comportamiento, sin normalizacion.Descubrir la forma de los datos
Cuando una columna
jsonbllega de una fuente externa, la primera pregunta es "que claves aparecen aqui". Desplegar las claves de cada fila y agruparlas te da un mapa de campos con sus frecuencias.SELECT key, COUNT(*) AS rows_with_key FROM users u, jsonb_object_keys(u.prefs) AS key GROUP BY key ORDER BY rows_with_key DESC;Este es el patron canonico: una tabla y una funcion de conjunto en el
FROMforman un joinLATERALimplicito, de modo que las claves de cada usuario se expanden en filas separadas. El resultado muestra al instante que campos son comunes y cuales son opcionales y raros.Comprobar que campos opcionales estan presentes
jsonb_object_keysayuda a encontrar filas que llevan (o no) un campo concreto. Para una sola comprobacion el operador?es mas comodo, pero recorrer las claves sirve para condiciones dinamicas.-- users who configured a newsletter preference at all SELECT id, email FROM users WHERE prefs ? 'newsletter'; -- equivalent shape check via the keys set SELECT id, email FROM users u WHERE EXISTS ( SELECT 1 FROM jsonb_object_keys(u.prefs) AS key WHERE key = 'newsletter' );El operador
?(contiene una clave de nivel superior) casi siempre es mas rapido y claro para un campo, sobre todo con un indice GIN enprefs. Recorrer conjsonb_object_keysse justifica cuando la condicion sobre la clave no es trivial, por ejemplo "tiene al menos una clave con prefijoflag_".Reunir claves con array_agg
A menudo quieres lo contrario de un despliegue: una lista compacta de claves por fila. Combinar
array_aggcon una subconsulta sobrejsonb_object_keyspliega las claves de vuelta en un array.SELECT u.id, u.email, ( SELECT array_agg(key ORDER BY key) FROM jsonb_object_keys(u.prefs) AS key ) AS configured_keys FROM users u WHERE u.prefs IS NOT NULL;El
ORDER BY keydentro dearray_aggda un orden estable y legible en lugar del interno dejsonb. Ese array es facil de comparar entre filas: encuentra usuarios con un conjunto de ajustes inusual, o construye un informe de "quien tiene que campos rellenos" sin volcar todo el JSON a la aplicacion.Otras bases de datos
MySQL no tiene un equivalente directo que devuelva un conjunto:
JSON_KEYS(prefs)devuelve un array JSON de claves como un solo valor, no un conjunto de filas. Para desplegarlo recurres aJSON_TABLE. En ClickHouse, el analisis de JSON usaJSONExtractKeys(prefs), que tambien produce un array; expandelo en filas conarrayJoin. Recuerda la regla comun: en los tres sistemas se trata solo de claves de nivel superior, asi que los objetos anidados se analizan en una pasada aparte.