给定类似于以下内容的现有数据结构:
CREATE TEMP TABLE sample (id int, metadata_array jsonb, text_id_one jsonb, text_id_two jsonb);
INSERT INTO sample
VALUES ('1', '[{"id": "textIdOne", "data": "foo"},{"id": "textIdTwo", "data": "bar"}]'), ('2', '[{"id": "textIdOne", "data": "baz"},{"id": "textIdTwo", "data": "fiz"}]');
我正在尝试将现有元数据列中的jsonb对象数组展开到同一个表中的新jsonb列中;我已经基于已知的固定ID键列表textIdOne
,textIdTwo
等创建了我。
我以为我接近使用jsonb_populate_recordset()
但后来意识到将按照所有jsonb对象的键填充列;不是我想要的。期望的结果是基于对象id的每列对象。
此操作中唯一另一个棘手的部分是我的JSON对象的id
值使用camelCase
并且似乎应该避免引用/引用的列名,但我不介意引用或修改列名称作为结束的手段&更新查询完成后,我可以根据需要手动更改列名。
我正在使用PostgreSQL 9.5.2
现有数据&结构:
id | metadata_array jsonb | text_id_one jsonb | text_id_two jsonb
---------------------------------------------------------------------------------------------
1 | [{"id": "textIdOne"...}, {"id": "textIdTwo"...}] | NULL | NULL
2 | [{"id": "textIdOne"...}, {"id": "textIdTwo"...}] | NULL | NULL
期望的结果:
id | metadata_array jsonb | text_id_one jsonb | text_id_two jsonb
-------------------------------------------------------------------------------
1 | [{"id": "textIdOne",... | {"id": "textIdOne"...} | {"id": "textIdTwo"...}
2 | [{"id": "textIdOne",... | {"id": "textIdOne"...} | {"id": "textIdTwo"...}
澄清:
感谢大家到目前为止的答案!虽然我知道完整的密钥列表(大约9个)但我不能指望顺序是一致的。
答案 0 :(得分:1)
如果所有json数组都包含两个新列的两个元素,那么使用固定路径,如dmfay的答案。否则,你应该使用jsonb_array_elements()两次取消数组,分别对text_id_one
和text_id_two
取消。
update sample t set
text_id_one = value1,
text_id_two = value2
from sample s,
jsonb_array_elements(s.metadata_array) as e1(value1),
jsonb_array_elements(s.metadata_array) as e2(value2)
where s.id = t.id
and value1->>'id' = 'textIdOne'
and value2->>'id' = 'textIdTwo'
returning t.*
如果数组中有两个以上的元素,这个变体可能更有效(也更方便):
update sample t
set
text_id_one = arr1->0,
text_id_two = arr2->0
from (
select
id,
jsonb_agg(value) filter (where value->>'id' = 'textIdOne') as arr1,
jsonb_agg(value) filter (where value->>'id' = 'textIdTwo') as arr2
from sample,
jsonb_array_elements(metadata_array)
group by id
) s
where t.id = s.id
returning t.*
答案 1 :(得分:0)
你说id列表是“固定的”; metadata_array
中对象的排序是否一致?你可以通过简单的遍历来做到这一点:
UPDATE sample
SET text_id_one = metadata_array->0,
text_id_two = metadata_array->1;