如何遍历 PostgreSQL jsonb 对象数组并修改元素?
How to iterate over PostgreSQL jsonb array of objects and modify elements?
给定 jsonb 数组和 PostgreSQL 12:
[{"data":"42","type":"TEMPERATURE"},{"data":"1.1","type":"PRESSURE"}]
需要转换为:
[{"data":"42","type":"temperature"},{"data":"1.1","type":"pressure"}]
是否有可能以某种方式遍历 jsonb 数组并仅将“type”值小写?
我试过了:
SELECT jsonb_agg(
jsonb_build_object(k, CASE WHEN k <> 'type' THEN v ELSE lower(v::text)::jsonb END)
)
FROM jsonb_array_elements(
'[{"data":"42","type":"TEMPERATURE"},{"data":"1.1","type":"PRESSURE"}]'::jsonb
) e(e), lateral jsonb_each(e) p(k, v)
但它将数据和类型对分成单独的元素。
[{"data": "42"}, {"type": "temperature"}, {"data": "1.1"}, {"type": "pressure"}]
在将对象聚合到数组中之前,您需要中间级别的嵌套来重建对象:为此,您可以使用横向连接。
我还建议跟踪每个对象在原始数组中的位置,这样您就可以将其传播到最终结果 - with ordinality
派上用场。
SELECT jsonb_agg(x.obj order by e.n)
FROM jsonb_array_elements('[{"data":"42","type":"TEMPERATURE"},{"data":"1.1","type":"PRESSURE"}]'::jsonb) with ordinality e(e, n)
CROSS JOIN LATERAL (
SELECT jsonb_object_agg(k, CASE WHEN k <> 'type' THEN v ELSE lower(v::text)::jsonb END)
FROM jsonb_each(e) p(k, v)
) x(obj)
| jsonb_agg |
| :--------------------------------------------------------------------------- |
| [{"data": "42", "type": "temperature"}, {"data": "1.1", "type": "pressure"}] |
给定 jsonb 数组和 PostgreSQL 12:
[{"data":"42","type":"TEMPERATURE"},{"data":"1.1","type":"PRESSURE"}]
需要转换为:
[{"data":"42","type":"temperature"},{"data":"1.1","type":"pressure"}]
是否有可能以某种方式遍历 jsonb 数组并仅将“type”值小写?
我试过了:
SELECT jsonb_agg(
jsonb_build_object(k, CASE WHEN k <> 'type' THEN v ELSE lower(v::text)::jsonb END)
)
FROM jsonb_array_elements(
'[{"data":"42","type":"TEMPERATURE"},{"data":"1.1","type":"PRESSURE"}]'::jsonb
) e(e), lateral jsonb_each(e) p(k, v)
但它将数据和类型对分成单独的元素。
[{"data": "42"}, {"type": "temperature"}, {"data": "1.1"}, {"type": "pressure"}]
在将对象聚合到数组中之前,您需要中间级别的嵌套来重建对象:为此,您可以使用横向连接。
我还建议跟踪每个对象在原始数组中的位置,这样您就可以将其传播到最终结果 - with ordinality
派上用场。
SELECT jsonb_agg(x.obj order by e.n)
FROM jsonb_array_elements('[{"data":"42","type":"TEMPERATURE"},{"data":"1.1","type":"PRESSURE"}]'::jsonb) with ordinality e(e, n)
CROSS JOIN LATERAL (
SELECT jsonb_object_agg(k, CASE WHEN k <> 'type' THEN v ELSE lower(v::text)::jsonb END)
FROM jsonb_each(e) p(k, v)
) x(obj)
| jsonb_agg | | :--------------------------------------------------------------------------- | | [{"data": "42", "type": "temperature"}, {"data": "1.1", "type": "pressure"}] |