PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Wstaw nowy element w kolumnie JSONB na podstawie wartości innego pola - postgres

Powinno to wystarczyć do uzupełnienia zapytania:

Stwórzmy próbne dane

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

Teraz rozbij tablicę za pomocą jsonb_array_elements z porządkiem, aby uzyskać indeks i właściwość

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

Wynik tego zapytania to:

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

Znajdziesz tam niezbędne informacje, których potrzebujesz, aby pobrać potrzebne elementy podrzędne, a także wszystkie indeksy potrzebne do zapytania.

Teraz, do ostatniej edycji, masz już żądane zapytanie:

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

W miejscu, w którym użyjesz id, ponieważ są to wiersze, które Cię interesują, aw indeksach uzyskałeś je z zapytania. A więc:

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 widać, łatwo się to robi bardzo nieprzyjemne.

Polecam albo użycie podejścia bardziej sql, to znaczy posiadanie funkcji w tabeli zamiast wewnątrz json, fk łączącego to z twoją tabelą ... Jeśli naprawdę potrzebujesz użyć json, na przykład, ponieważ domena jest naprawdę złożony i zdefiniowany na poziomie aplikacji oraz bardzo elastyczny. W takim razie polecam wykonanie aktualizacji w kodzie aplikacji




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak wykonać zapytanie LIKE dla klucza jsonb?

  2. Jak utworzyć histogram w PostgreSQL

  3. Jak obliczyć średnią kroczącą w PostgreSQL

  4. Jak uzyskać wymiarowość kolumny ARRAY?

  5. Migracja Railsów:Bigint na PostgreSQL wydaje się zawodzić?