我正在尝试编写查询以更新PostgreSQL数据库中一些深层嵌套的JSON。我仍然要掌握整个JSONB系统。在我的特殊情况下,我试图识别和更新大型JSON捆绑包的多个子部分。特定行可能会深深地包含一个数组。在该数组中,许多元素可能需要根据模式进行更改。
下面是一些代码,用于创建一个示例数据库表,其中仅包含一行,以表达我所面临的问题。这是假数据,因为实际数据是专有数据。
CREATE TABLE "Units" (
id serial primary key,
data jsonb
);
INSERT INTO "Units" (data)
VALUES
('
{
"animals": {
"mammals": [
{
"id": 0,
"population": 700
},
{
"id": 1
},
{
"id": 2,
"population": 500
}
],
"birds": [
{
"id": 3,
"population": 3000
},
{
"id": 4
}
]
}
}
');
在这种情况下,我想向包含密钥animals -> mammals
的{{1}}内的每个实体添加密钥。我想添加一个名为population
的新密钥,其值应为extinct
。
这是我已经解决的查询。
false
我发现此查询易于理解,并且一次执行一次脱机修改的性能合理。但是,它有一个致命的缺陷。因为UPDATE "Units" as outside
SET data = jsonb_set(outside.data, ('{animals,mammals,' || (inside.ordinality - 1) || ',extinct}')::text[], 'false'::jsonb, true)
FROM (
SELECT id, ordinality
FROM "Units"
INNER JOIN jsonb_array_elements(data->'animals'->'mammals') with ordinality
ON id = id
WHERE value ? 'population' AND NOT (value ? 'extinct')
) as inside
WHERE outside.id = inside.id;
仅在每一行上起作用,所以此查询仅更新找到UPDATE
键的两个实体之一。该查询将必须运行两次以更新在第一行中找到的每个实体。现在,假设这是一个更复杂的JSON对象,并且此表中还有很多行。这将是一场噩梦,必须一遍又一遍地更新每个最后一个实体。
如何调整此population
,以便它会更新每个匹配行中的每个匹配实体?
这是上面所有内容的DBFiddle。