Tabla de contenidos
PostgreSQL proporciona dos tipos para almacenar datos JSON: json y jsonb. El tipo json almacena una copia exacta del texto de entrada, que debe volver a analizarse cada vez que se procesa. Por otro lado, el tipo jsonb almacena los datos JSON en un formato binario descompuesto que hace que su entrada sea ligeramente más lenta debido a la sobrecarga de conversión añadida, pero significativamente más rápida de procesar, ya que no es necesario volver a analizarla. El tipo jsonb también admite indexación.
En MobilityDB, los tipos textset y ttext se utilizan para representar, respectivamente, conjuntos de valores JSON y valores JSON temporales. Además, el tipo jsonb sirve como tipo base para definir los tipos jsonbset y tjsonb. La mayoría de las funciones y operadores descritos en los capítulos anteriores para los tipos conjunto y temporal también son aplicables a los tipos JSON correspondientes. Además, hay funciones específicas definidas para estos tipos, que se derivan de las funciones correspondientes de los tipos json y jsonb.
En este capítulo, describimos los tipos JSON de MobilityDB y sus operaciones asociadas. Remitimos a la documentación de PostgreSQL para una explicación detallada de los tipos json y jsonb y su funcionalidad. Hemos buscado habilitar la misma sintaxis de las funciones originales de PostgreSQL para los tipos correspondientes de MobilityDB, como se ilustra en este documento.
Considere por ejemplo el operador ->, que extrae un campo de objeto JSON con una clave dada.
SELECT jsonb '{"unit": "km", "speed": 10}' -> text 'speed';
-- 10
Aplicar el mismo operador a un conjunto JSONB y a un valor JSONB temporal produce los siguientes resultados
SELECT jsonbset '{"{\"unit\": \"km\", \"speed\": 10}",
"{\"unit\": \"km\", \"speed\": 20}"}' -> text 'speed';
-- {10, 20}
SELECT tjsonb '[{"unit": "km", "speed": 10}@2001-01-01,
{"unit": "km", "speed": 20}@2001-01-02]' -> text 'speed';
-- {["10"@2001-01-01, "20"@2001-01-02]}
que se obtienen aplicando el operador de PostgreSQL -> a cada elemento del conjunto JSONB y a cada instante del valor JSONB temporal.
PostgreSQL proporciona las siguientes operaciones sobre valores JSONB con sus propios nombres y operadores. MobilityDB las nombra como sus equivalentes sobre conjuntos JSONB y JSONB temporales, de modo que una consulta que utiliza estos nombres se ejecuta sin cambios en todos los motores del ecosistema (“Valores base provistos por el anfitrión”). Los operadores de PostgreSQL conservan sus símbolos.
Extrae un campo de objeto JSON especificado por una clave
jsonbObjectField(jsonb,text) → jsonb jsonbObjectFieldText(jsonb,text) → text
SELECT jsonbObjectField(jsonb '{"a": {"b": 1}}', 'a');
-- {"b": 1}
SELECT jsonbObjectFieldText(jsonb '{"a": "x"}', 'a');
-- x
Extrae un valor JSON especificado por una ruta
jsonbExtractPath(jsonb,path text[]) → jsonb jsonbExtractPathText(jsonb,path text[]) → text
SELECT jsonbExtractPath(jsonb '{"a": {"b": [10, 20]}}', ARRAY['a', 'b', '1']);
-- 20
SELECT jsonbExtractPathText(jsonb '{"a": {"b": "z"}}', ARRAY['a', 'b']);
-- z
Extrae un elemento de un arreglo JSON
jsonbArrayElement(jsonb,integer) → jsonb jsonbArrayElementText(jsonb,integer) → text
Los elementos se numeran desde cero, y un entero negativo cuenta desde el final del arreglo.
SELECT jsonbArrayElement(jsonb '[1, [2, 3]]', 1); -- [2, 3] SELECT jsonbArrayElement(jsonb '[1, 2, 3]', -1); -- 3 SELECT jsonbArrayElementText(jsonb '["x", "y"]', 0); -- x
Devuelve el número de elementos de un arreglo JSON
jsonbArrayLength(jsonb) → integer
SELECT jsonbArrayLength(jsonb '[1, 2, 3]'); -- 3
Devuelve los elementos de un arreglo JSON como filas
jsonbArrayElements(jsonb) → setof jsonb jsonbArrayElementsText(jsonb) → setof text
SELECT * FROM jsonbArrayElements(jsonb '[1, "two", {"three": 3}]');
-- 1
-- "two"
-- {"three": 3}
SELECT * FROM jsonbArrayElementsText(jsonb '[1, "two"]');
-- 1
-- two
Devuelve los campos de un objeto JSON como filas de una clave y un valor
jsonbEach(jsonb) → setof (key text,value jsonb) jsonbEachText(jsonb) → setof (key text,value text)
SELECT * FROM jsonbEach(jsonb '{"a": 1, "b": [2]}') ORDER BY key;
-- a | 1
-- b | [2]
SELECT * FROM jsonbEachText(jsonb '{"a": 1, "b": "x"}') ORDER BY key;
-- a | 1
-- b | x
Devuelve las claves de un objeto JSON como filas
jsonbObjectKeys(jsonb) → setof text
SELECT * FROM jsonbObjectKeys(jsonb '{"b": 1, "a": 2}') ORDER BY 1;
-- a
-- b
Devuelve el texto indentado de un valor JSON
jsonbPretty(jsonb) → text
SELECT jsonbPretty(jsonb '{"a": 1}');
-- {
-- "a": 1
-- }
Concatena dos valores JSON
jsonbConcat(jsonb,jsonb) → jsonb
SELECT jsonbConcat(jsonb '{"a": 1}', jsonb '{"b": 2}');
-- {"a": 1, "b": 2}
Elimina de un valor JSON una clave, las claves de un arreglo, un elemento de arreglo o el elemento en una ruta
jsonbDelete(jsonb,text) → jsonb jsonbDeleteArray(jsonb,text[]) → jsonb jsonbDeleteIndex(jsonb,integer) → jsonb jsonbDeletePath(jsonb,path text[]) → jsonb
SELECT jsonbDelete(jsonb '{"a": 1, "b": 2}', 'a');
-- {"b": 2}
SELECT jsonbDeleteArray(jsonb '{"a": 1, "b": 2, "c": 3}', ARRAY['a', 'c']);
-- {"b": 2}
SELECT jsonbDeleteIndex(jsonb '[1, 2, 3]', -1);
-- [1, 2]
SELECT jsonbDeletePath(jsonb '{"a": {"b": 1, "c": 2}}', ARRAY['a', 'b']);
-- {"a": {"c": 2}}
¿Existe un texto, o alguno o todos los textos de un arreglo, como clave de nivel superior o elemento de arreglo de un valor JSON?
jsonbExists(jsonb,text) → boolean jsonbExistsAny(jsonb,text[]) → boolean jsonbExistsAll(jsonb,text[]) → boolean
SELECT jsonbExists(jsonb '{"a": 1}', 'a');
-- true
SELECT jsonbExistsAny(jsonb '{"a": 1}', ARRAY['b', 'a']);
-- true
SELECT jsonbExistsAll(jsonb '{"a": 1}', ARRAY['b', 'a']);
-- false
¿Contiene el primer valor JSON al segundo, o está contenido en él?
jsonbContains(jsonb,jsonb) → boolean jsonbContained(jsonb,jsonb) → boolean
SELECT jsonbContains(jsonb '{"a": 1, "b": 2}', jsonb '{"a": 1}');
-- true
SELECT jsonbContained(jsonb '{"a": 1}', jsonb '{"a": 1, "b": 2}');
-- true
Devuelve un valor JSON con el elemento en una ruta establecido en un valor
jsonbSet(jsonb,path text[],val jsonb,create_missing boolean=true) → jsonb jsonbSetLax(jsonb,path text[],val jsonb,create_missing boolean=true, handle_null text='use_json_null') → jsonb
El elemento se añade cuando no existe y create_missing es verdadero. La función jsonbSetLax trata un valor NULL según handle_null, que es uno de 'raise_exception', 'use_json_null', 'delete_key' o 'return_target'.
SELECT jsonbSet(jsonb '{"a": 1}', ARRAY['b'], jsonb '2');
-- {"a": 1, "b": 2}
SELECT jsonbSet(jsonb '{"a": 1}', ARRAY['b'], jsonb '2', false);
-- {"a": 1}
SELECT jsonbSetLax(jsonb '{"a": 1}', ARRAY['a'], NULL);
-- {"a": null}
SELECT jsonbSetLax(jsonb '{"a": 1}', ARRAY['a'], NULL, true, 'delete_key');
-- {}
Devuelve un valor JSON con un valor insertado en una ruta
jsonbInsert(jsonb,path text[],val jsonb,after boolean=false) → jsonb
SELECT jsonbInsert(jsonb '[1, 3]', ARRAY['1'], jsonb '2'); -- [1, 2, 3] SELECT jsonbInsert(jsonb '[1, 3]', ARRAY['1'], jsonb '2', true); -- [1, 3, 2]
Devuelve un valor JSON sin sus campos de objeto cuyo valor es nulo
jsonbStripNulls(jsonb,strip_in_arrays boolean=false) → jsonb
El último argumento indica si los elementos de arreglo nulos también se eliminan.
SELECT jsonbStripNulls(jsonb '{"a": null, "b": [1, null]}');
-- {"b": [1, null]}
SELECT jsonbStripNulls(jsonb '{"a": null, "b": [1, null]}', true);
-- {"b": [1]}
¿Devuelve la ruta JSON algún elemento para un valor JSON?
jsonbPathExists(jsonb,jsonpath,vars jsonb='{}',silent boolean=false) → boolean
jsonbPathExistsTz(jsonb,jsonpath,vars jsonb='{}',silent boolean=false) → boolean
El último argumento suprime los siguientes errores: campo de objeto o elemento de arreglo faltante, tipo de elemento JSON inesperado, errores de fecha/hora y numéricos; el resultado de un error suprimido es NULL. Las funciones que terminan en Tz comparan valores de fecha y hora entre zonas horarias.
SELECT jsonbPathExists(jsonb '{"a": [1, 2, 3]}', '$.a[*] ? (@ > 2)');
-- true
SELECT jsonbPathExists(jsonb '{"a": [1, 2, 3]}', '$.a[*] ? (@ > $x)', '{"x": 5}');
-- false
Devuelve el resultado de una comprobación de predicado de ruta JSON para un valor JSON
jsonbPathMatch(jsonb,jsonpath,vars jsonb='{}',silent boolean=false) → boolean
jsonbPathMatchTz(jsonb,jsonpath,vars jsonb='{}',silent boolean=false) → boolean
SELECT jsonbPathMatch(jsonb '{"a": [1, 2, 3]}', 'exists($.a[*] ? (@ > 2))');
-- true
Devuelve los elementos que una ruta JSON devuelve para un valor JSON, como filas, como un arreglo JSON, o el primero de ellos
jsonbPathQuery(jsonb,jsonpath,vars jsonb='{}',silent boolean=false) → setof jsonb
jsonbPathQueryTz(jsonb,jsonpath,vars jsonb='{}',silent boolean=false) → setof jsonb
jsonbPathQueryArray(jsonb,jsonpath,vars jsonb='{}',silent boolean=false) → jsonb
jsonbPathQueryArrayTz(jsonb,jsonpath,vars jsonb='{}',silent boolean=false) → jsonb
jsonbPathQueryFirst(jsonb,jsonpath,vars jsonb='{}',silent boolean=false) → jsonb
jsonbPathQueryFirstTz(jsonb,jsonpath,vars jsonb='{}',silent boolean=false) → jsonb
SELECT * FROM jsonbPathQuery(jsonb '{"a": [1, 2, 3]}', '$.a[*] ? (@ >= 2)');
-- 2
-- 3
SELECT jsonbPathQueryArray(jsonb '{"a": [1, 2, 3]}', '$.a[*] ? (@ >= 2)');
-- [2, 3]
SELECT jsonbPathQueryFirst(jsonb '{"a": [1, 2, 3]}', '$.a[*] ? (@ >= 2)');
-- 2
Compara dos valores JSON, o devuelve el valor hash de un valor JSON
jsonb {=, <>, <, <=, >=, >} jsonb → boolean
cmp(jsonb,jsonb) → integer
hash(jsonb) → integer
hashExtended(jsonb,seed bigint) → bigint
Los operadores son los de PostgreSQL, y las funciones eq, ne, lt, le, ge y gt responden como ellos, junto con cmp, que devuelve -1, 0 o 1. Las funciones hash y hashExtended responden como las funciones jsonb_hash y jsonb_hash_extended de PostgreSQL.
SELECT eq(jsonb '{"a": 1}', jsonb '{"a": 1}');
-- true
SELECT cmp(jsonb '1', jsonb '2');
-- -1