sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur går man med i jsonb-arrayelement i Postgres?

Om du antar minst Postgres 9.5, kommer detta att göra 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;

Hur?

  1. Ta bort jsonb array, producerar 1 rad per arrayelement:

    jsonb_array_elements(p.content) AS c(elem)
    
  2. För varje element LEFT JOIN till images på de villkor som
    a. nyckeln 'type' har värdet 'image':c.elem->>'type' = 'image'
    b. UUID i image_id matchar:i.id = (elem->>'image_id')::uuid

  3. För bildtyper, där en matchande bild hittades

    c.elem->>'type' = 'image' AND i.id IS NOT NULL
    

    ta bort nyckeln 'image_id' och lägg till den relaterade bildraden som jsonb värde:

    elem - 'image_id' || jsonb_build_object('image', i)
    

    Behåll annars det ursprungliga elementet.

  4. Aggregera de modifierade elementen igen till ett nytt content kolumn med jsonb_agg() .

  5. Ovillkorligt LEFT JOIN LATERAL resultatet till posts och välj alla kolumner, ersätt bara p.content med den genererade ersättningen c.content

  6. I den yttre SELECT , konvertera hela raden till jsonb med en enkel to_jsonb() .

Alla jsonb funktioner finns dokumenterade i manualen här.




  1. hur man endast väljer unika värden från relaterade tabeller

  2. BÖRJA...SLUTA vs BÖRJA TRANSAKTION...ÅTGÄRDER

  3. Rails + MySQL på Mavericks - Biblioteket är inte laddat:libmysqlclient.18.dylib

  4. ORA-01000:maximala öppna markörer överskrids när Spring SimpleJDBCCall används