JSON数组中JSON对象的PostgreSQL集合字段
我有一张这样的桌子:JSON数组中JSON对象的PostgreSQL集合字段,sql,json,postgresql,Sql,Json,Postgresql,我有一张这样的桌子: | id (SERIAL) | game (TEXT) | players (JSONB) | +-------------+-------------+-----------------+ | 1 | chess | [{name: Joe, role: admin}, {name: Mike, role: user}] | | 2 | football | [{name: Foo, role: user}, {n
| id (SERIAL) | game (TEXT) | players (JSONB) |
+-------------+-------------+-----------------+
| 1 | chess | [{name: Joe, role: admin}, {name: Mike, role: user}] |
| 2 | football | [{name: Foo, role: user}, {name: Bar, role: user}] |
+-------------+-------------+-----------------+
| id (SERIAL) | game (TEXT) | players (JSONB) |
+-------------+-------------+-----------------+
| 1 | chess | [{name: Joe, role: user}, {name: Mike, role: user}] |
| 2 | football | [{name: Foo, role: user}, {name: Bar, role: user}] |
+-------------+-------------+-----------------+
我想将玩家(Joe)的角色设置为特定游戏(国际象棋)中的特定值(用户),因此结果如下所示:
| id (SERIAL) | game (TEXT) | players (JSONB) |
+-------------+-------------+-----------------+
| 1 | chess | [{name: Joe, role: admin}, {name: Mike, role: user}] |
| 2 | football | [{name: Foo, role: user}, {name: Bar, role: user}] |
+-------------+-------------+-----------------+
| id (SERIAL) | game (TEXT) | players (JSONB) |
+-------------+-------------+-----------------+
| 1 | chess | [{name: Joe, role: user}, {name: Mike, role: user}] |
| 2 | football | [{name: Foo, role: user}, {name: Bar, role: user}] |
+-------------+-------------+-----------------+
是否可以通过一个查询来实现这一点?这可以通过在每次更新时重新创建json数组来实现 用于表创建和示例数据插入的SQL:
CREATE TABLE test_table(
id BIGSERIAL PRIMARY KEY ,
game TEXT,
players JSONB
);
INSERT INTO test_table(game, players)
VALUES
('chess', '[{"name": "Joe", "role": "admin"}, {"name": "Mike", "role": "user"}]'),
('football', '[{"name": "Foo", "role": "user"}, {"name": "Bar", "role": "user"}]');
插入的数据:
+----+----------+----------------------------------------------------------------------+
| id | game | players |
+----+----------+----------------------------------------------------------------------+
| 1 | chess | [{"name": "Joe", "role": "admin"}, {"name": "Mike", "role": "user"}] |
| 2 | football | [{"name": "Foo", "role": "user"}, {"name": "Bar", "role": "user"}] |
+----+----------+----------------------------------------------------------------------+
更新查询:
WITH json_rows AS
(SELECT id, jsonb_array_elements(players) as json_data FROM test_table
WHERE game = 'chess'),
updated_rows AS (
SELECT
id,
array_to_json(array_agg(
CASE WHEN json_data -> 'name' = '"Joe"'
THEN jsonb_set(json_data, '{role}', '"user"')
ELSE json_data END)) as updated_json
FROM json_rows
GROUP BY id
)
UPDATE test_table SET players = u.updated_json
FROM updated_rows u
WHERE test_table.id = u.id;
查询结果:
+----+----------+---------------------------------------------------------------------+
| id | game | players |
+----+----------+---------------------------------------------------------------------+
| 2 | football | [{"name": "Foo", "role": "user"}, {"name": "Bar", "role": "user"}] |
| 1 | chess | [{"name": "Joe", "role": "user"}, {"name": "Mike", "role": "user"}] |
+----+----------+---------------------------------------------------------------------+
查询的工作方式如下:
game
属性对其进行过滤。这是通过创建json_行
CTE来完成的注意:如您所见,在当前的实现中,json数组被重新创建(仅在需要更新的行中)。这可能会导致数组中元素的顺序发生变化 我知道这会发生的。。。谢谢,但我知道你应该避免在关系数据库中使用JSON。我的用例非常特殊,需要JSON,否则我不会使用它。