更新 jsonb 列以替换特定元素
Update jsonb column to replace specific element
我想更新 jsonb 列以替换其中的数组元素,例如 Tv 到 TV。我在 table.
上使用 5M 行的 postgresql 12.4
前 10 行:
categories
["Air Conditioner", "Kitchen", "Bedding/Linens", "Parking", "Tv", "Child Friendly", "Internet", "Laundry"]
["Hot Tub", "Air Conditioner", "Kitchen", "Bedding/Linens", "Tv", "Wheelchair Accessible", "Pool", "Internet", "Laundry"]
["Hot Tub", "Air Conditioner", "Kitchen", "Bedding/Linens", "Balcony/Terrace", "Parking", "Tv", "Wheelchair Accessible", "Child Friendly", "Pool", "Internet", "Laundry"]
["Balcony/Terrace", "Kitchen", "Bedding/Linens", "Tv", "Wheelchair Accessible", "Internet", "Laundry"]
["Air Conditioner", "Kitchen", "Bedding/Linens", "Parking", "Tv", "Pool", "Internet", "Laundry"]
["Hot Tub", "Air Conditioner", "Kitchen", "Bedding/Linens", "Parking", "Balcony/Terrace", "Tv", "Child Friendly", "Internet", "Pet Friendly", "Laundry"]
["Hot Tub", "Air Conditioner", "Kitchen", "Bedding/Linens", "Balcony/Terrace", "Parking", "Tv", "Wheelchair Accessible", "Pool", "Internet", "Laundry"]
["Air Conditioner", "Kitchen", "Bedding/Linens", "Tv", "Wheelchair Accessible", "Internet", "Laundry"]
["Kitchen", "Bedding/Linens", "Parking", "Tv", "Internet", "Laundry"]
["Air Conditioner", "Kitchen", "Bedding/Linens", "Parking", "Tv", "Wheelchair Accessible", "Internet", "Laundry"]
什么是有效的:
UPDATE test_jsonb_update
SET amenity_categories = replace(amenity_categories::TEXT,'"Tv"','"TV"')::jsonb
WHERE id < 10;
我想要的:
我想知道在 jsonb 列上更新该元素的其他替代方法。我看过这个例子
并且我想在我的设备上使用类似 jsonb_set
的东西
案也。让我知道其他替代方案和最佳做法,因为我有 500 万条记录需要更新
恕我直言,你的方法是最有效的。以任何其他方式(如果你想保持顺序!)你需要将数组元素扩展到单独的行(要么检索旧"Tv"
的索引以设置新的 "TV"
使用 jsonb_set 或字符串 search/replace) 到相同的位置并重新聚合所有...
SELECT
id,
jsonb_agg(CASE WHEN elem = 'Tv' THEN 'TV' ELSE elem END) as new_array
FROM mytable,
jsonb_array_elements_text(mydata) as elem
GROUP BY id
如果你真的想使用 jsonb_set
(我相信这在这里没有意义)你可以这样做:
SELECT
jsonb_set(mydata, ARRAY[s.elem_id]::text[], '"TV"') - 'Tv'
FROM mytable t
JOIN (
SELECT
id,
elem_id
FROM mytable,
jsonb_array_elements_text(mydata) WITH ORDINALITY as elem(value, elem_id)
WHERE elem.value = 'Tv'
)s ON s.id = t.id
- 扩展数组元素并显示它们的索引
WITH ORDINALITY
- 现在您可以使用这些索引将新的
"TV"
元素放置到 jsonb_set()
的正确位置
- 之后您需要从更新的数组中删除旧的
"Tv"
元素。
最后更新:
UPDATE mytable t
SET mydata = s.my_array
FROM (
-- query
) s
WHERE t.id = s.id
您的 json 数组的顺序似乎不固定,所以这应该可以完成工作并避免任何取消嵌套。
UPDATE ...
SET amenity_categories = (amenity_categories - 'Tv') || jsonb '["TV"]'
WHERE amenity_categories ? 'Tv';
我想更新 jsonb 列以替换其中的数组元素,例如 Tv 到 TV。我在 table.
上使用 5M 行的 postgresql 12.4前 10 行:
categories
["Air Conditioner", "Kitchen", "Bedding/Linens", "Parking", "Tv", "Child Friendly", "Internet", "Laundry"]
["Hot Tub", "Air Conditioner", "Kitchen", "Bedding/Linens", "Tv", "Wheelchair Accessible", "Pool", "Internet", "Laundry"]
["Hot Tub", "Air Conditioner", "Kitchen", "Bedding/Linens", "Balcony/Terrace", "Parking", "Tv", "Wheelchair Accessible", "Child Friendly", "Pool", "Internet", "Laundry"]
["Balcony/Terrace", "Kitchen", "Bedding/Linens", "Tv", "Wheelchair Accessible", "Internet", "Laundry"]
["Air Conditioner", "Kitchen", "Bedding/Linens", "Parking", "Tv", "Pool", "Internet", "Laundry"]
["Hot Tub", "Air Conditioner", "Kitchen", "Bedding/Linens", "Parking", "Balcony/Terrace", "Tv", "Child Friendly", "Internet", "Pet Friendly", "Laundry"]
["Hot Tub", "Air Conditioner", "Kitchen", "Bedding/Linens", "Balcony/Terrace", "Parking", "Tv", "Wheelchair Accessible", "Pool", "Internet", "Laundry"]
["Air Conditioner", "Kitchen", "Bedding/Linens", "Tv", "Wheelchair Accessible", "Internet", "Laundry"]
["Kitchen", "Bedding/Linens", "Parking", "Tv", "Internet", "Laundry"]
["Air Conditioner", "Kitchen", "Bedding/Linens", "Parking", "Tv", "Wheelchair Accessible", "Internet", "Laundry"]
什么是有效的:
UPDATE test_jsonb_update
SET amenity_categories = replace(amenity_categories::TEXT,'"Tv"','"TV"')::jsonb
WHERE id < 10;
我想要的:
我想知道在 jsonb 列上更新该元素的其他替代方法。我看过这个例子
并且我想在我的设备上使用类似 jsonb_set
的东西
案也。让我知道其他替代方案和最佳做法,因为我有 500 万条记录需要更新
恕我直言,你的方法是最有效的。以任何其他方式(如果你想保持顺序!)你需要将数组元素扩展到单独的行(要么检索旧"Tv"
的索引以设置新的 "TV"
使用 jsonb_set 或字符串 search/replace) 到相同的位置并重新聚合所有...
SELECT
id,
jsonb_agg(CASE WHEN elem = 'Tv' THEN 'TV' ELSE elem END) as new_array
FROM mytable,
jsonb_array_elements_text(mydata) as elem
GROUP BY id
如果你真的想使用 jsonb_set
(我相信这在这里没有意义)你可以这样做:
SELECT
jsonb_set(mydata, ARRAY[s.elem_id]::text[], '"TV"') - 'Tv'
FROM mytable t
JOIN (
SELECT
id,
elem_id
FROM mytable,
jsonb_array_elements_text(mydata) WITH ORDINALITY as elem(value, elem_id)
WHERE elem.value = 'Tv'
)s ON s.id = t.id
- 扩展数组元素并显示它们的索引
WITH ORDINALITY
- 现在您可以使用这些索引将新的
"TV"
元素放置到jsonb_set()
的正确位置
- 之后您需要从更新的数组中删除旧的
"Tv"
元素。
最后更新:
UPDATE mytable t
SET mydata = s.my_array
FROM (
-- query
) s
WHERE t.id = s.id
您的 json 数组的顺序似乎不固定,所以这应该可以完成工作并避免任何取消嵌套。
UPDATE ...
SET amenity_categories = (amenity_categories - 'Tv') || jsonb '["TV"]'
WHERE amenity_categories ? 'Tv';