Actualización : con PostgreSQL 9.5 , hay algunas jsonb
funciones de manipulación dentro de PostgreSQL (pero ninguna para json
; se requieren conversiones para manipular los json
valores).
Fusionar 2 (o más) objetos JSON (o concatenar matrices):
SELECT jsonb '{"a":1}' || jsonb '{"b":2}', -- will yield jsonb '{"a":1,"b":2}'
jsonb '["a",1]' || jsonb '["b",2]' -- will yield jsonb '["a",1,"b",2]'
Por lo tanto, configurar una tecla simple se puede hacer usando:
SELECT jsonb '{"a":1}' || jsonb_build_object('<key>', '<value>')
Donde <key>
debe ser una cadena, y <value>
puede ser cualquier tipo que to_jsonb()
acepte.
Para establecer un valor profundo en una jerarquía JSON , jsonb_set()
se puede usar la función:
SELECT jsonb_set('{"a":[null,{"b":[]}]}', '{a,1,b,0}', jsonb '{"c":3}')
-- will yield jsonb '{"a":[null,{"b":[{"c":3}]}]}'
Lista completa de parámetros de jsonb_set()
:
jsonb_set(target jsonb,
path text[],
new_value jsonb,
create_missing boolean default true)
path
también puede contener índices de matriz JSON y los enteros negativos que aparecen allí cuentan desde el final de las matrices JSON. Sin embargo, un índice de matriz JSON no existente pero positivo agregará el elemento al final de la matriz:
SELECT jsonb_set('{"a":[null,{"b":[1,2]}]}', '{a,1,b,1000}', jsonb '3', true)
-- will yield jsonb '{"a":[null,{"b":[1,2,3]}]}'
Para insertar en la matriz JSON (mientras se conservan todos los valores originales) , jsonb_insert()
se puede usar la función ( en 9.6+; esta función solo, en esta sección ):
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b,0}', jsonb '2')
-- will yield jsonb '{"a":[null,{"b":[2,1]}]}', and
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b,0}', jsonb '2', true)
-- will yield jsonb '{"a":[null,{"b":[1,2]}]}'
Lista completa de parámetros de jsonb_insert()
:
jsonb_insert(target jsonb,
path text[],
new_value jsonb,
insert_after boolean default false)
De nuevo, los enteros negativos que aparecen en el path
recuento desde el final de las matrices JSON.
Entonces, f.ex. agregar al final de una matriz JSON se puede hacer con:
SELECT jsonb_insert('{"a":[null,{"b":[1,2]}]}', '{a,1,b,-1}', jsonb '3', true)
-- will yield jsonb '{"a":[null,{"b":[1,2,3]}]}', and
Sin embargo, esta función funciona de manera ligeramente diferente (que jsonb_set()
) cuando path
in target
es la clave de un objeto JSON. En ese caso, solo agregará un nuevo par clave-valor para el objeto JSON cuando no se use la clave. Si se usa, generará un error:
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,c}', jsonb '[2]')
-- will yield jsonb '{"a":[null,{"b":[1],"c":[2]}]}', but
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b}', jsonb '[2]')
-- will raise SQLSTATE 22023 (invalid_parameter_value): cannot replace existing key
La eliminación de una clave (o un índice) de un objeto JSON (o de una matriz) se puede hacer con el -
operador:
SELECT jsonb '{"a":1,"b":2}' - 'a', -- will yield jsonb '{"b":2}'
jsonb '["a",1,"b",2]' - 1 -- will yield jsonb '["a","b",2]'
La eliminación, desde lo profundo de una jerarquía JSON, se puede hacer con el #-
operador:
SELECT '{"a":[null,{"b":[3.14]}]}' #- '{a,1,b,0}'
-- will yield jsonb '{"a":[null,{"b":[]}]}'
Para 9.4 , puede usar una versión modificada de la respuesta original (a continuación), pero en lugar de agregar una cadena JSON, puede agregarla directamente a un objeto json json_object_agg()
.
Respuesta original : es posible (sin plpython o plv8) en SQL puro también (pero necesita 9.3+, no funcionará con 9.2)
CREATE OR REPLACE FUNCTION "json_object_set_key"(
"json" json,
"key_to_set" TEXT,
"value_to_set" anyelement
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')::json
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> "key_to_set"
UNION ALL
SELECT "key_to_set", to_json("value_to_set")) AS "fields"
$function$;
SQLFiddle
Editar :
Una versión, que establece múltiples claves y valores:
CREATE OR REPLACE FUNCTION "json_object_set_keys"(
"json" json,
"keys_to_set" TEXT[],
"values_to_set" anyarray
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')::json
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> ALL ("keys_to_set")
UNION ALL
SELECT DISTINCT ON ("keys_to_set"["index"])
"keys_to_set"["index"],
CASE
WHEN "values_to_set"["index"] IS NULL THEN 'null'::json
ELSE to_json("values_to_set"["index"])
END
FROM generate_subscripts("keys_to_set", 1) AS "keys"("index")
JOIN generate_subscripts("values_to_set", 1) AS "values"("index")
USING ("index")) AS "fields"
$function$;
Edición 2 : como señaló @ErwinBrandstetter , estas funciones anteriores funcionan como un llamado UPSERT
(actualiza un campo si existe, lo inserta si no existe). Aquí hay una variante, que solo UPDATE
:
CREATE OR REPLACE FUNCTION "json_object_update_key"(
"json" json,
"key_to_set" TEXT,
"value_to_set" anyelement
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT CASE
WHEN ("json" -> "key_to_set") IS NULL THEN "json"
ELSE (SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> "key_to_set"
UNION ALL
SELECT "key_to_set", to_json("value_to_set")) AS "fields")::json
END
$function$;
Edición 3 : Aquí hay una variante recursiva, que puede establecer ( UPSERT
) un valor de hoja (y usa la primera función de esta respuesta), ubicada en una ruta de clave (donde las claves solo pueden referirse a objetos internos, no se admiten matrices internas):
CREATE OR REPLACE FUNCTION "json_object_set_path"(
"json" json,
"key_path" TEXT[],
"value_to_set" anyelement
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT CASE COALESCE(array_length("key_path", 1), 0)
WHEN 0 THEN to_json("value_to_set")
WHEN 1 THEN "json_object_set_key"("json", "key_path"[l], "value_to_set")
ELSE "json_object_set_key"(
"json",
"key_path"[l],
"json_object_set_path"(
COALESCE(NULLIF(("json" -> "key_path"[l])::text, 'null'), '{}')::json,
"key_path"[l+1:u],
"value_to_set"
)
)
END
FROM array_lower("key_path", 1) l,
array_upper("key_path", 1) u
$function$;
Actualización : las funciones están compactadas ahora.
select json_object_set_key((select data from test where data->>'b' = '2'), 'b', 'two');
un mensaje de errorERROR: could not determine polymorphic type because input has type "unknown"
UPSERT
, no unUPDATE
. Si la clave aún no existe en el campo json, se agrega. Mire a esta pregunta relacionada para un realUPDATE
: stackoverflow.com/questions/7711432/… (Esto es para un tipo compuesto, pero el principal es similar para json.)$2::text
.Con 9.5 use jsonb_set-
donde body es un tipo de columna jsonb.
fuente
upper
así:update objects set body=jsonb_set(body, '{name}', upper('"Mary"'), true) where id=1;
no reconoce, o cómo puedo lograr el mismo comportamiento? thxCon Postgresql 9.5 se puede hacer siguiendo:
O
Alguien preguntó cómo actualizar muchos campos en el valor jsonb a la vez. Supongamos que creamos una tabla:
Luego INSERTAMOS una fila experimental:
Luego ACTUALIZAMOS la fila:
Que hace lo siguiente:
Seleccionar los datos:
Resultará en:
Para actualizar el campo dentro, no use el operador concat
||
. Use jsonb_set en su lugar. Lo cual no es simple:Usando el operador concat para {c, c1} por ejemplo:
Eliminará {c, c2} y {c, c3}.
Para obtener más potencia, busque potencia en la documentación de funciones jgres de postgresql . Uno podría estar interesado en el
#-
operador, lajsonb_set
función y también lajsonb_insert
función.fuente
UPDATE users SET profile = profile || '{"lastname":"Washington"}' WHERE profile->>'name' = 'George Washington';
Para construir sobre las respuestas de @ pozs, aquí hay un par de funciones más de PostgreSQL que pueden ser útiles para algunos. (Requiere PostgreSQL 9.3+)
Eliminar por clave: elimina un valor de la estructura JSON por clave.
Eliminar recursivo por clave: elimina un valor de la estructura JSON por la ruta de la clave. (requiere la
json_object_set_key
función de @ pozs )Ejemplos de uso:
fuente
Esto parece estar funcionando en PostgreSQL 9.5
fuente
Si su tipo de campo es json, lo siguiente funcionará para usted.
El operador '-' elimina el par clave / valor o el elemento de cadena del operando izquierdo. Los pares clave / valor se corresponden en función de su valor clave.
Operador '||' concatena dos valores jsonb en un nuevo valor jsonb.
Dado que estos son operadores jsonb, solo necesita escribir a :: jsonb
Más información: Funciones y operadores JSON
Puedes leer mi nota aquí
fuente
Con PostgreSQL 9.4, hemos implementado la siguiente función de Python. También puede funcionar con PostgreSQL 9.3.
Ejemplo de uso:
Tenga en cuenta que para un empleador anterior, he escrito un conjunto de funciones C para manipular datos JSON como texto (no como un
json
ojsonb
tipo) para PostgreSQL 7, 8 y 9. Por ejemplo, extraer datos conjson_path('{"obj":[12, 34, {"num":-45.67}]}', '$.obj[2]['num']')
, establecer datos con,json_path_set('{"obj":[12, 34, {"num":-45.67}]}', '$.obj[2]['num']', '99.87')
etc. Tomó alrededor de 3 días de trabajo, por lo que si necesita que se ejecute en sistemas heredados y tenga tiempo de sobra, puede valer la pena el esfuerzo. Me imagino que la versión C es mucho más rápida que la versión python.fuente
Aunque lo siguiente no satisfará esta solicitud (la función json_object_agg no está disponible en PostgreSQL 9.3), lo siguiente puede ser útil para cualquiera que busque un || operador para PostgreSQL 9.4, tal como se implementará en el próximo PostgreSQL 9.5:
fuente
Escribí una pequeña función para mí que funciona de forma recursiva en Postgres 9.4. Aquí está la función (espero que funcione bien para usted):
Aquí está el uso de muestra:
Como puede ver, analice en profundidad y actualice / agregue valores donde sea necesario.
fuente
Esto funcionó para mí, cuando intentaba actualizar un campo de tipo cadena.
¡Espero que ayude a alguien más!
Suponiendo que la tabla nombre_tabla tiene una columna jsonb llamada cuerpo y desea cambiar body.some_key = 'value'
fuente
Lamentablemente, no he encontrado nada en la documentación, pero puede usar alguna solución alternativa, por ejemplo, podría escribir alguna función extendida.
Por ejemplo, en Python:
y entonces
fuente
value
también requerirá unaloads
hora de establecer valores no numéricos (como cuerdasjs[key] = loads(value)
) - De lo contrario:select json_update('{"a":"a"}', 'a', to_json('b')); -> {"a": "\"b\""}
El siguiente fragmento de plpython puede ser útil.
fuente
Encontré que las respuestas anteriores son usuarios de PostgreSQL experimentados adecuados, de ahí mi respuesta:
Suponga que tiene una tabla-columna de tipo JSONB con el siguiente valor:
supongamos que queremos establecer un nuevo valor en la fila:
y en su lugar coloque el valor:
Usamos la función json_set () para asignar un nuevo valor a la clave13
los parámetros para jsonb_set ()
en " target ": colocaré el nombre de columna jsonb (esta es la columna de la tabla que se está modificando)
" ruta ": es la "ruta de teclas json" que conduce a (e incluye) la clave que vamos a sobrescribir
" new_value ": este es el nuevo valor que asignamos
en nuestro caso, queremos actualizar el valor de key13 que reside en key1 (key1 -> key13):
por lo tanto, la sintaxis de la ruta es: '{key1, key13}' (La ruta fue la parte más difícil de descifrar, porque los tutoriales son terribles)
fuente
También puede incrementar las claves atómicamente dentro de
jsonb
esta manera:Clave indefinida -> asume el valor inicial de 0.
Para una explicación más detallada, vea mi respuesta aquí: https://stackoverflow.com/a/39076637
fuente
Para aquellos que usan
mybatis
, aquí hay una declaración de actualización de ejemplo:Parámetros:
qid
, la clave para el campo.value
, es una cadena json válida, para el valor de campo,por ejemplo , convertida de objeto a cadena json a través de
jackson
,fuente
Entonces, por ejemplo, mi cadena se ve así: {"a1": {"a11": "x", "a22": "y", "a33": "z"}}
Actualizo jsons usando la tabla temporal, que es lo suficientemente buena para una cantidad de datos bastante pequeña (<1.000.000). Encontré una forma diferente, pero luego me fui de vacaciones y lo olvidé ...
Entonces. la consulta será algo como esto:
Tiene más que ver con cadenas que con json, pero funciona. Básicamente, extrae todos los datos en la tabla temporal, crea una cadena mientras conecta los agujeros de concat con los datos de los que realizó una copia de seguridad y los convierte en jsonb.
Json_set podría ser más eficiente, pero todavía me estoy acostumbrando. La primera vez que intenté usarlo, estropeé la cadena por completo ...
fuente
Si está realizando esta consulta con un cliente de lenguaje de programación, por ejemplo
python pycopg2
, desde oNode Postgres
, asegúrese de analizar primero los datos nuevos a JSON.Puede parecer fácilmente que un diccionario de Python es lo mismo que un objeto JSON, pero no hace primero json.dumps en el diccionario.
Un simple fragmento de python:
def change_destination(self,parcel_id,destlatlng): query="UPDATE parcels SET destlatlng = '{}' WHERE parcel_id ={};".format(json.dumps(destlatlng), parcel_id) self.cursor.execute(query2) self.connection.commit()
fuente