[英]Postgresql update JSONB object to array
I don't know why, but probably PHP persisted some of my data as object and some of them as array.我不知道为什么,但可能 PHP 将我的一些数据保存为 object,其中一些保存为数组。 My table looks something like:我的桌子看起来像:
seller_info_address Table: seller_info_address 表:
ID (INT) | address (JSONB) |
------------+--------------------------------------------------|
1 | {"addressLines":{"0":"Technology Park",...},...} |
2 | {"addressLines":["Technology Park",...],...} |
Some addressLines are objects:一些地址线是对象:
{
"addressLines": {
"0": "Technology Park",
"1": "Blanchard Road",
"3": "Dublin",
"4": "2"
},
"companyName": "...",
"emailAddress": [],
"...": "..."
}
Some addressLines are arrays:一些地址线是 arrays:
{
"addressLines": [
"Technology Park",
"Blanchard Road",
"Dublin",
"2"
],
"companyName": "...",
"emailAddress": [],
"...": "..."
}
I would like to equalize the data with a SQL query, but I'm not sure how to do it.我想用 SQL 查询来均衡数据,但我不确定该怎么做。 All addressLines
persisted as object should be updated to array form.所有addressLines
持久化为 object 应更新为数组形式。
I am grateful for help, thanks!感谢帮助,谢谢!
You can convert the objects to an array using this:您可以使用以下方法将对象转换为数组:
select id, (select jsonb_agg(e.val order by e.key::int)
from jsonb_each(sia.address -> 'addressLines') as e(key,val))
from seller_info_address sia
where jsonb_typeof(address -> 'addressLines') = 'object'
The where condition makes sure we only do this for addresslines that are not an array. where 条件确保我们只对不是数组的地址行执行此操作。
The aggregation used can also be used inside an UPDATE statement:使用的聚合也可以在 UPDATE 语句中使用:
update seller_info_address
set address = jsonb_set(address, '{addressLines}',
(select jsonb_agg(e.val order by e.key::int)
from jsonb_each(address -> 'addressLines') as e(key,val))
)
where jsonb_typeof(address -> 'addressLines') = 'object';
Ok, I have now found a solution myself.好的,我现在自己找到了解决方案。 Definitely not the most eloquent solution.绝对不是最 eloquent 的解决方案。 I'm sure there's a nicer and more efficient one, but it works...我敢肯定有一个更好,更高效的方法,但是它确实有效...
DROP FUNCTION update_address_object_to_array(id INTEGER);
CREATE OR REPLACE FUNCTION
update_address_object_to_array(id INTEGER)
RETURNS VOID AS
$UPDATE_ADDRESS_OBJECT_TO_ARRAY$
BEGIN
UPDATE seller_info_address
SET address = jsonb_set(address, '{addressLines}', (
SELECT CASE
WHEN jsonb_agg(addressLines) IS NOT NULL THEN jsonb_agg(addressLines)
ELSE '[]'
END
FROM seller_info_address sia,
jsonb_each(address #> '{addressLines}') as t(key, addressLines)
WHERE jsonb_typeof(sia.address -> 'addressLines') = 'object'
AND seller_info_id = update_address_object_to_array.id
), true)
WHERE seller_info_id = update_address_object_to_array.id
AND jsonb_typeof(address -> 'addressLines') = 'object';
END
$UPDATE_ADDRESS_OBJECT_TO_ARRAY$
LANGUAGE 'plpgsql';
SELECT update_address_object_to_array(sia.seller_info_id)
FROM seller_info_address sia
WHERE jsonb_typeof(address -> 'addressLines') = 'object';
The inner SELECT fetches all lines in the addressLines
object using jsonb_each
and then aggregates them into an array using jsonb_agg
.内部 SELECT 使用 jsonb_each 获取addressLines
object 中的所有行,然后使用jsonb_each
将它们聚合到一个数组jsonb_agg
。 The conditional expressions is to prevented null cases.条件表达式是为了防止 null 个案例。
The result is then stored in the UPDATE via jsonb_set
to the required position in the json. The WHERES should be self-explanatory.然后将结果存储在 UPDATE 中,通过jsonb_set
到 json 中所需的 position。WHERES 应该是不言自明的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.