Za předpokladu alespoň Postgres 9.5 to bude fungovat:
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;
Jak?
-
Zrušte vnoření
jsonb
pole, vytváří 1 řádek na prvek pole:jsonb_array_elements(p.content) AS c(elem)
-
Pro každý prvek
LEFT JOIN
naimages
za podmínek, které
a. klíč 'type' má hodnotu 'image':c.elem->>'type' = 'image'
b. UUID vimage_id
odpovídá:i.id = (elem->>'image_id')::uuid
-
Pro typy obrázků, kde byl nalezen odpovídající obrázek
c.elem->>'type' = 'image' AND i.id IS NOT NULL
odstraňte klíč 'image_id' a přidejte související řádek obrázku jako
jsonb
hodnota:elem - 'image_id' || jsonb_build_object('image', i)
Jinak ponechte původní prvek.
-
Znovu agregujte upravené prvky do nového
content
sloupec sjsonb_agg()
. -
Bezpodmínečně
LEFT JOIN LATERAL
výsledek doposts
a vyberte všechny sloupce, nahraďte pouzep.content
s vygenerovanou náhradouc.content
-
Ve vnějším
SELECT
, převeďte celý řádek najsonb
pomocí jednoduchéhoto_jsonb()
.
Vše jsonb
funkce jsou popsány v návodu zde.