Capítulo 15. Tipos JSON en MobilityDB

Tabla de contenidos

Operaciones sobre valores JSONB
Operaciones sobre conjuntos JSONB
Valores JSONB temporales
Validez de los valores JSONB temporales
Entrada y salida
Constructores
Conversiones
Accesores
Transformaciones
Operaciones JSON temporales
Restricciones
Operaciones de caja delimitadora
Comparaciones
Agregaciones
Indexación

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.

Operaciones sobre valores JSONB

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