sql >> Databáze >  >> RDS >> PostgreSQL

Vložit novou položku do sloupce JSONB na základě hodnoty jiného pole - postgres

Toto by mělo stačit k dokončení dotazu:

Pojďme vytvořit simulovaná 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
      }
    ]
  }
]');

Nyní rozložte pole pomocí jsonb_array_elements s ordinalitou, abyste získali index a vlastnost

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);

Výsledek tohoto dotazu je:

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

Zde máte potřebné informace, které potřebujete k načtení dílčích prvků, které potřebujete, a také všechny indexy, které jste potřebovali pro svůj dotaz.

Nyní, ke konečné úpravě, jste již měli dotaz, který jste chtěli:

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}]}';

V tom, kde použijete id, protože to jsou řádky, které vás zajímají, a v indexech, které jste získali z dotazu. Takže:

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;

Jak můžete vidět, je to velmi ošklivé.

Doporučil bych buď použít přístup více sql, to znamená mít funkce v tabulce místo uvnitř json, fk, který to propojí s vaší tabulkou...Pokud opravdu potřebujete použít json, například protože doména je skutečně komplexní a definovaný na aplikační úrovni a velmi flexibilní. Pak bych doporučil provést aktualizace v kódu aplikace




  1. Oracle - Klonovací tabulka - Struktura, datová omezení a vše

  2. Rozdíl mezi BINARY(16) a CHAR(32) při ukládání MD5 do databáze

  3. Mapování PostgreSQL textu[][] typu a typu Java

  4. Při použití poolConnection nebo CreateConnection felixge/node-mysql