postgresql: jsonb обновляет несколько ключей в одном запросе

У меня есть следующие строки postgresql в виде строки JSONB:

{age:26}

И я хотел бы заменить его так, чтобы он выглядел так:

{age: 30, city: "new york city"}

Как я могу сделать это в postgressql? Кто-то упоминал об использовании jsonb_set(), но я не видел примеров обновления нескольких ключей в одном запросе.


person ApathyBear    schedule 31.10.2016    source источник
comment
обновление нескольких ключей postgres jsonb_set   -  person Abelisto    schedule 31.10.2016


Ответы (5)


Используйте jsonb_set() внутри jsonb_set()

jsonb_set(jsonb_set('{age:26}'::jsonb,'{age}','"30"'::jsonb)::jsonb,'{city}','"new york city"'::jsonb)
person SHAKU    schedule 18.12.2016
comment
Стандартный способ обновления нескольких ключей, указанный в ответе здесь, не помог, пока этот ответ идеально подходил для моего случая, так как мне нужно было обновить несколько ключей, один из которых является обычным значением, а другой — массивом jsonb. - person uLan; 26.10.2017

Постгрескл великолепен. Вы также можете использовать string concatenation operator, ||

UPDATE wooden_table
SET doc = doc
    || '{"color" : "red"}' 
    || '{"hardness" : "1H"}';

Этот метод также будет работать со значениями JSON внутри стороны значений.

person anakha    schedule 04.03.2021

хотя вы можете просто вложить действия jsonb_set, это становится довольно ужасно читать.

Вместо этого вы можете использовать jsonb_object

SET my_column = my_column || jsonb_object(
    array[ -- keys
        'age',
        'city',
        'visits'
    ],
    array[ -- values
        31::text,
        'Johannesburg'::text,
        ((my_column#>>'{visits}')::int + 1)::text -- increment
    ]
)

Примечание: вы потеряете безопасность типов, так как он обрабатывает только текстовые поля, но вы можете выполнять частичные обновления (добавлять только те поля, которые хотите обновить), и если вы обрабатываете это с другого языка, он имеет тенденцию быть довольно программируемым, если ваша абстракция SQL не слишком предписывающий

person WiR3D    schedule 04.03.2021
comment
это отлично подходит для текстовых значений, но не работает со значениями json. - person anakha; 05.03.2021
comment
да, вы теряете безопасность типов. но даже со счетчиками я обнаружил, что это небольшое неудобство. Это позволило мне использовать один столбец для динамического добавления новой изменяемой статистики без обновления схемы. - person WiR3D; 05.03.2021

С sqlalchemy:

from sqlalchemy import func, and_, any_, cast
from sqlalchemy.dialects.postgresql import JSONB


db.session.query(Model).filter(
    Model.id == any_(ids)
).update({
    Model.your_jsonb_field: cast(
        Model.your_jsonb_field,
        JSONB,
    ).concat(
        func.jsonb_build_object('key1', 'value1'),
    ).concat(
        func.jsonb_build_object('key2', 'value2'),
    )
}, synchronize_session='fetch')
person Nikolay Baluk    schedule 30.06.2021

При обновлении данных вы можете использовать столбец jsonb, а также создавать данные формата json из имеющихся у вас атрибутов. При выполнении jsonb следует помнить четыре вещи:

  1. передать первый параметр в функцию jsonb_set - это цель (где вы не хотите заменить)
  2. Ключ json
  3. json значение
  4. если это новый столбец сделать истинным
select jsonb_set(jsonb_set('{}'::jsonb,'{age}','30',true)::jsonb,'{city}',to_jsonb('hyd'::text),true)::jsonb;
person Shashi555    schedule 18.03.2020