postgresql 从jsonb值中删除键和/或数组元素

zf2sa74q  于 2024-01-07  发布在  PostgreSQL
关注(0)|答案(1)|浏览(196)

我们在表metaTable中有一个列metajsonb

{
 "records": {
    record1: {
        "GUID-1": {
           values: ["GUID-value-1", "GUID-value-2", "GUID-value-3"],
           type: "..."
        },
        "GUID-2": {
           values: ["GUID-value-4", "GUID-value-5"],
           type: "..."
        },
        "GUID-3": {
           values: ["GUID-value-6"],
           type: "..."
        },
        "GUID-4": {
           values: ["GUID-value-7"],
           type: "..."
        }
    }
 },
 "miscellaneous": {
    .....
 }
}

字符串
"GUID-1""GUID-2""GUID-3""GUID-4"是关键。
"GUID-value-1""GUID-value-2""GUID-value-3""GUID-value-4""GUID-value-5""GUID-value-6""GUID-value-7"是值。

  • 键和值都是唯一的。*

我们尝试从JSON文档中删除在给定数组中列出的键和/或嵌套数组元素。例如:
["GUID-3", "GUID-value-4", "GUID-value-1", "GUID-value-2", "GUID-value-3", "GUID-value-7", "GUID-4", "random-GUID1", "random-GUID2"]
预期结果:

{
 "records": {
    record1: {
        "GUID-2": {
           values: ["GUID-value-5"],
           type: "..."
        }
    }
 },
 "miscellaneous": {
    .....
 }
}


注1:"GUID-1"被删除,因为数组"values"是空的。
注2:此SQL将应用于每一行。
我试过:

update metaTable
set "meta" = 
json_set("meta", '{records, record1, GUID-1, values}', ("meta" -> 'records' -> 'record1' -> 'GUID-1' -> values) - '{GUID-value-1, GUID-value-2", GUID-value-3}'::text[])


只有当我已经知道GUID- 1是键,GUID-value-1, GUID-value-2, and GUID-value-3是值时,这才有效。
有没有一种通用的方法可以在一个SQL查询中完成它,而不需要事先弄清楚每个查询的角色?

anauzrmj

anauzrmj1#

这里有一个基本的解决方案:

SELECT t.id, jsonb_pretty(jsonb_set(meta, '{records,record1}', r.upd_rec))
FROM   tbl t
CROSS  JOIN (
   SELECT '{GUID-3,GUID-value-4,GUID-value-1,GUID-value-2,GUID-value-3,GUID-value-7,GUID-4,random-GUID1,random-GUID2}'::text[]  -- input here!
   ) d(del_arr)
CROSS  JOIN LATERAL (
   SELECT jsonb_object_agg(r.k, jsonb_set(r.v, '{values}', (r.v -> 'values') - d.del_arr))          
   FROM   jsonb_each(t.meta #> '{records,record1}') r(k,v)
   WHERE  r.k <> ALL (d.del_arr)
   AND   (r.v -> 'values') - d.del_arr <> jsonb '[]'
   ) r(upd_rec)
ORDER  BY t.id;

字符串
fiddle
你可以从它构建你的UPDATE。有很多需要解释的。它可以进一步优化。
但我觉得这太具体了,对公众没有用处。

相关问题