Dengan asumsi setidaknya Postgres 9.5, ini akan berhasil:
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;
Bagaimana?
-
Hapus sarang
jsonb
array, menghasilkan 1 baris per elemen array:jsonb_array_elements(p.content) AS c(elem)
-
Untuk setiap elemen
LEFT JOIN
keimages
dengan syarat bahwa
a. Kunci 'type' memiliki nilai 'image':c.elem->>'type' = 'image'
b. UUID diimage_id
cocok:i.id = (elem->>'image_id')::uuid
-
Untuk jenis gambar, di mana gambar yang cocok ditemukan
c.elem->>'type' = 'image' AND i.id IS NOT NULL
hapus kunci 'image_id' dan tambahkan baris gambar terkait sebagai
jsonb
nilai:elem - 'image_id' || jsonb_build_object('image', i)
Jika tidak, pertahankan elemen aslinya.
-
Gabungkan kembali elemen yang dimodifikasi ke
content
baru kolom denganjsonb_agg()
. -
Tanpa syarat
LEFT JOIN LATERAL
hasilnya menjadiposts
dan pilih semua kolom, hanya gantip.content
denganc.content
pengganti yang dihasilkan -
Di bagian luar
SELECT
, konversikan seluruh baris kejsonb
denganto_jsonb()
sederhana .
Semua jsonb
fungsi didokumentasikan dalam manual di sini.