Giả sử ít nhất Postgres 9.5, điều này sẽ thực hiện công việc:
SELECT jsonb_pretty(to_jsonb(p)) AS post_row_as_json
FROM (
SELECT id, title, author_id, c.content
FROM posts p
LEFT JOIN LATERAL (
SELECT jsonb_agg(
CASE WHEN c.elem->>'type' = 'image' AND i.id IS NOT NULL
THEN elem - 'image_id' || jsonb_build_object('image', i)
ELSE c.elem END) AS content
FROM jsonb_array_elements(p.content) AS c(elem)
LEFT JOIN images i ON c.elem->>'type' = 'image'
AND i.id = (elem->>'image_id')::uuid
) c ON true
) p;
Làm thế nào?
-
Bỏ kết nối
jsonb
mảng, tạo ra 1 hàng cho mỗi phần tử mảng:jsonb_array_elements(p.content) AS c(elem)
-
Đối với mỗi phần tử
LEFT JOIN
thànhimages
với các điều kiện mà
a. Chìa khóa 'type' có giá trị 'image':c.elem->>'type' = 'image'
b. UUID trongimage_id
khớp với:i.id = (elem->>'image_id')::uuid
-
Đối với các loại hình ảnh, nơi tìm thấy hình ảnh phù hợp
c.elem->>'type' = 'image' AND i.id IS NOT NULL
xóa khóa 'image_id' và thêm hàng hình ảnh liên quan dưới dạng
jsonb
giá trị:elem - 'image_id' || jsonb_build_object('image', i)
Khác giữ nguyên phần tử ban đầu.
-
Tổng hợp lại các phần tử đã sửa đổi thành một
content
mới cột cójsonb_agg()
.
-
Không điều kiện
LEFT JOIN LATERAL
kết quả đếnposts
và chọn tất cả các cột, chỉ thay thếp.content
vớic.content
thay thế được tạo -
Trong
SELECT
bên ngoài , chuyển đổi toàn bộ hàng thànhjsonb
với mộtto_jsonb()
đơn giản .
Tất cả jsonb
các chức năng được ghi lại trong sách hướng dẫn tại đây.