Hvis man antager mindst Postgres 9.5, vil dette gøre jobbet:
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;
Hvordan?
-
Fjern
jsonb
matrix, der producerer 1 række pr. matrixelement:jsonb_array_elements(p.content) AS c(elem)
-
For hvert element
LEFT JOIN
tilimages
på de betingelser, som
a. Nøglen 'type' har værdien 'image':c.elem->>'type' = 'image'
b. UUID'et iimage_id
matcher:i.id = (elem->>'image_id')::uuid
-
For billedtyper, hvor der blev fundet et matchende billede
c.elem->>'type' = 'image' AND i.id IS NOT NULL
fjern nøglen 'image_id' og tilføj den relaterede billedrække som
jsonb
værdi:elem - 'image_id' || jsonb_build_object('image', i)
Ellers behold det originale element.
-
Saml de ændrede elementer igen til et nyt
content
kolonne medjsonb_agg()
. -
Ubetinget
LEFT JOIN LATERAL
resultatet tilposts
og vælg alle kolonner, erstat kunp.content
med den genererede erstatningc.content
-
I den ydre
SELECT
, konverter hele rækken tiljsonb
med en simpelto_jsonb()
.
Alle jsonb
funktioner er dokumenteret i manualen her.