sql >> Database teknologi >  >> RDS >> PostgreSQL

Indsæt nyt element i JSONB-kolonnen baseret på værdien af ​​andet felt - postgres

Dette burde være nok information til at fuldføre forespørgslen:

Lad os skabe de falske data

create table a (id serial primary key , b jsonb);

insert into a (b)
values ('[
  {
    "name": "test",
    "features": [
      {
        "name": "feature1",
        "granted": false
      },
      {
        "name": "feature2",
        "granted": true
      }
    ]
  },
  {
    "name": "another-name",
    "features": [
      {
        "name": "feature1",
        "granted": false
      },
      {
        "name": "feature2",
        "granted": true
      }
    ]
  }
]');

Eksploder nu arrayet ved hjælp af jsonb_array_elements med ordinalitet for at få indekset og egenskaben

select first_level.id, position, feature_position, feature
from (select a.id, arr.*
      from a,
           jsonb_array_elements(a.b) with ordinality arr (elem, position)
      where elem ->> 'name' = 'test') first_level,
     jsonb_array_elements(first_level.elem -> 'features') with ordinality features (feature, feature_position);

Resultatet af denne forespørgsel er:

1,1,1,"{""name"": ""feature1"", ""granted"": false}"
1,1,2,"{""name"": ""feature2"", ""granted"": true}"

Der har du den nødvendige information, som du skal bruge for at hente de underelementer, du har brug for, samt alle de indekser, du har brug for til din forespørgsel.

Nu, til den endelige redigering, havde du allerede den forespørgsel, du ønskede:

UPDATE my_table SET modules =
    jsonb_insert(my_column, '{0, features, 0}', '{"name": "newFeature", "granted": false}')
WHERE my_column ->> 'name' = 'test' AND my_column @> '{"features": [{"name":"feature1", "granted": false}]}';

I hvor skal du bruge id'et, fordi det er de rækker, du er interesseret i, og i indekserne fik du dem fra forespørgslen. Så:

UPDATE my_table SET modules =
    jsonb_insert(my_column, '{' || exploded_info.position::string || ', features, ' || exploded_info.feature_position || '}', '{"name": "newFeature", "granted": false}') from (/* previous query */) as exploded_info
WHERE exploded_info.id = my_table.id and exploded_info.feature -> 'granted' = false;

Som du kan se, bliver dette nemt meget grimt.

Jeg vil anbefale enten at bruge en mere sql tilgang, det vil sige at have funktioner i en tabel i stedet for inde i en json, en fk der forbinder det til din tabel...Hvis du virkelig har brug for at bruge json, for eksempel fordi domænet er virkelig kompleks og defineret på applikationsniveau og meget fleksibel. Så vil jeg anbefale at lave opdateringerne inde i app-koden




  1. Formater SQLite-forespørgselsresultater som en HTML-tabel

  2. Sådan laver du dynamisk pivot i oracle PL SQL

  3. Sådan tilføjes og trækkes dag, måned, år i dato gennem MySql Query

  4. Sådan ændres webporten i EBS 12.2