Добавить элемент в объект JSON в Postgres
У меня есть текстовое поле в базе данных (postgres 9.2.1) с json blob. Это похоже на что-то похожее, кроме всего лишь на одну строку, очевидно:
{
"keyword": {
"checked": "1",
"label": "Keyword"
},
"agency_name": {
"checked": "0",
"label": "Agency Name"
}
}
Мне нужно добавить элемент в массив json, чтобы он выглядел так:
{
"keyword": {
"checked": "1",
"label": "Keyword"
},
"something_new": {
"checked": "1",
"label": "Something New"
},
"agency_name": {
"checked": "0",
"label": "Agency Name"
}
}
Я не так обеспокоен размещением нового элемента массива. Это может быть после agency_name. Есть ли простой способ сделать это в postgres?
Ответы
Ответ 1
PostgreSQL еще не имеет большого смысла в функциях поддержки JSON: все, что я вижу, это такие, как array_to_json
, что может быть полезно, если есть соответствующий способ преобразования исходного JSON в массив, который вы могли бы затем выполните манипуляции, чтобы добавить этот дополнительный элемент перед тем, как перейти к JSON.
Возможно, лучше всего использовать язык PL для управления JSON. Одним из очевидных будет PLV8, который обеспечивает функциональность программирования JavaScript в PostgreSQL. Вы должны написать пользовательскую функцию в JavaScript, которая соответствующим образом управляет блоком JSON:
Конечно, многие другие языки PL, такие как Java, Python или Perl, могут быть так же хороши при работе с данными JSON и, возможно, их проще установить в вашей системе. Пользовательские функции могут быть записаны в каждом из них, если вы их настроили.
Ответ 2
Даже у меня была та же проблема, я хотел динамически добавлять новые элементы в jsonb [].
Предположим, что column_jsonb [] = [{ "name" : "xyz", "age" : "12" }]
UPDATE table_name
SET column_jsonb[] = array_append(column_jsonb[],'{"name":"abc","age":"22"}');
Результат: [{ "name" : "xyz", "age" : "12" }, { "name" : "abc", "age" : "22" }]
Ответ 3
Если обновление до PG9.5.1, вы можете использовать команду sql ||
для объединения jsonb, example
select '{"a":1}'::jsonb || '{"a":2, "b":2}'::jsonb
вернет {"a": 2, "b": 2}
Если вы не можете перейти на pg9.5.1, ИМХО, выполнение задания в коде будет лучшим выбором. Вы можете разобрать старую строку jsonb в виде карты, а затем обновить карту, затем преобразовать в строку и обновить db-запись.
Ответ 4
Версия 9.5 предоставляет jsonb_set функцию create_missing = TRUE.
В любых других случаях используйте следующую информацию для добавления информации:
SELECT (trim( trailing '}' from data::text) || ', "c":2}')::json
Чтобы добавить/заменить новое значение, используя более правильный способ:
UPDATE t
SET data=t3.data
FROM t AS t1
INNER JOIN
(
SELECT id, json_object_agg(t.k,t.v)
FROM
(
SELECT *
FROM (SELECT id, json_object_keys(data) as k, data->json_object_keys(data) as v FROM t) as t2
WHERE t.k != 'c'
UNION ALL
SELECT id, 'c'::text as k, '"new value"'::json as v FROM t1
) as t3
GROUP by id
) as t4 ON (t1.id=t4.id)
Чтобы удалить ключ:
UPDATE t
SET data=t3.data
FROM t AS t1
INNER JOIN
(
SELECT id, json_object_agg(t.k,t.v)
FROM (SELECT id, json_object_keys(data) as k, data->json_object_keys(data) as v FROM t) as t2
WHERE t.k != 'c'
GROUP by id
) as t4 ON (t1.id=t4.id)
Ответ 5
У меня была именно эта проблема. Это решение является довольно "чистой" манипуляцией с объектом, и я предпочитаю функции "sql" для plpgsql. Главное - дезагрегировать с помощью json_each - дать вам запись - а затем создать запись из
CREATE OR REPLACE FUNCTION json_extend_object(
input_object json,
append_key text,
append_object json)
RETURNS json AS
$BODY$
select json_object_agg (((json_val)::record).key, ((json_val)::record).value)
from (
select json_val
from (select json_each (input_object) as json_val) disaggr
where ((json_val::record).key != append_key)
union
select newvals
from (
select append_key, append_object
) newvals
) to_rows;
$BODY$
LANGUAGE sql IMMUTABLE
;