Ответ 1
Вы можете сделать это с помощью jsonb
, по крайней мере, с помощью Postgres 9.5.2.
Учитывая следующую таблицу:
CREATE TABLE users (id INT, counters JSONB NOT NULL DEFAULT '{}');
С данными образца:
INSERT INTO users (id, counters) VALUES (1, '{"bar": 0}');
SELECT * FROM users;
id | counters
----+------------
1 | {"bar": 0}
Вы можете увеличить "бар" в JSON атомарно:
UPDATE users SET counters = counters || CONCAT('{"bar":', COALESCE(counters->>'bar','0')::int + 1, '}')::jsonb WHERE id = 1;
SELECT * FROM users;
id | counters
----+------------
1 | {"bar": 1}
Это не красиво, но оно работает.
Здесь он разбит по этапам:
Вы можете установить ключ в jsonb
на явное значение OR
, используя объекты jsonb:
UPDATE users SET counters = counters || '{"bar": 314}'::jsonb WHERE id = 1;
SELECT * FROM users;
id | counters
----+--------------
1 | {"bar": 314}
Теперь все, что осталось сделать, это динамически построить строку с помощью CONCAT(), одновременно демонстрируя приращение (на 27) клавиши undefined (по умолчанию начальное значение с помощью COALESCE()):
UPDATE users SET counters = counters || CONCAT('{"foo":', COALESCE(counters->>'foo','0')::int + 27, '}')::jsonb WHERE id = 1;
SELECT * FROM users;
id | counters
----+-------------------------
1 | {"bar": 314, "foo": 27}
Боб твой дядя.:)