Обновить массив JSON в Postgres с помощью определенного ключа

#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:

Это действительно неприятно, потому что

  1. Обновление элемента внутри массива JSON всегда требует расширения массива
  2. Сверху: массив является вложенным
  3. Идентификатор для обновляемых элементов является родственным, а не родительским, что означает, что вам нужно фильтровать по родственному

Итак, я придумал решение, но я хочу отказаться: вам следует избегать делать это как обычное действие с базой данных! Лучше было бы:

  1. Разбор вашего JSON в серверной части и выполнение операций в вашем серверном коде
  2. Нормализуйте JSON в своей базе данных, если это будет обычной задачей, то есть: создайте таблицы с соответствующими столбцами и извлеките свой JSON в структуру таблицы. Не храните целые объекты JSON в базе данных! Это сделало бы каждую задачу намного проще и невероятно более производительной!

демонстрация: db<>скрипка

 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
 
  1. Извлеките вложенные элементы массива по одному элементу в строку
  2. Замените function значение. Обратите внимание на приведения от типа json к типу jsonb . Это необходимо, потому что нет json_set() функции, но только jsonb_set() . Естественно, если у вас просто есть type jsonb , приведения не нужны.
  3. Заменить numValue значение
  4. Повторно сгруппируйте массив
  5. Замените where значение исходного объекта JSON на вновь созданный объект array.