#json #postgresql #jsonb
#json #postgresql #jsonb
Вопрос:
У меня есть сложный массив, который выглядит следующим образом в столбце таблицы:
{
"sometag": {},
"where": [
{
"id": "Krishna",
"nick": "KK",
"values": [
"0"
],
"function": "ADD",
"numValue": [
"0"
]
},
{
"id": "Krishna1",
"nick": "KK1",
"values": [
"0"
],
"function": "SUB",
"numValue": [
"0"
]
}
],
"anotherTag": [],
"TagTag": {
"tt": "tttttt",
"tt1": "tttttt"
}
В этом массиве я хочу обновить функцию и числовое значение id: «Кришна».
Пожалуйста, помогите.
Комментарии:
1. Что вы пробовали до сих пор? Каков ваш ожидаемый результат? Почему numValue является массивом?
2. numValue может иметь несколько значений. Ожидайте вывода: { «sometag»: {}, «where»: [ { «id»: «Krishna», «nick»: «KK», «values»: [ «0» ], «function»: «ADDITION», «numValue»: [ «0»,»1″ ] }, { «id»: «Krishna1», «nick»: «KK1», «values»: [ «0» ], «function»: «SUB», «numValue»: [ «0» ] } ], » Другой тег»: [],»TagTag»: { «tt»: «tttttt», «tt1»: «tttttt» } }
3. Это было бы намного проще при правильно нормализованной модели данных
Ответ №1:
Это действительно неприятно, потому что
- Обновление элемента внутри массива JSON всегда требует расширения массива
- Сверху: массив является вложенным
- Идентификатор для обновляемых элементов является родственным, а не родительским, что означает, что вам нужно фильтровать по родственному
Итак, я придумал решение, но я хочу отказаться: вам следует избегать делать это как обычное действие с базой данных! Лучше было бы:
- Разбор вашего JSON в серверной части и выполнение операций в вашем серверном коде
- Нормализуйте JSON в своей базе данных, если это будет обычной задачей, то есть: создайте таблицы с соответствующими столбцами и извлеките свой JSON в структуру таблицы. Не храните целые объекты JSON в базе данных! Это сделало бы каждую задачу намного проще и невероятно более производительной!
SELECT
jsonb_set( -- 5
(SELECT mydata::jsonb FROM mytable),
'{where}',
updated_array
)::json
FROM (
SELECT
jsonb_agg( -- 4
CASE WHEN array_elem ->> 'id' = 'Krishna' THEN
jsonb_set( -- 3
jsonb_set(array_elem.value::jsonb, '{function}', '"ADDITION"'::jsonb), -- 2
'{numValue}',
'["0","1"]'::jsonb
)
ELSE array_elem::jsonb END
) as updated_array
FROM mytable,
json_array_elements(mydata -> 'where') array_elem -- 1
) s
- Извлеките вложенные элементы массива по одному элементу в строку
- Замените
function
значение. Обратите внимание на приведения от типаjson
к типуjsonb
. Это необходимо, потому что нетjson_set()
функции, но толькоjsonb_set()
. Естественно, если у вас просто есть typejsonb
, приведения не нужны. - Заменить
numValue
значение - Повторно сгруппируйте массив
- Замените
where
значение исходного объекта JSON на вновь созданный объект array.