PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Masukkan item baru di kolom JSONB berdasarkan nilai bidang lain - postgres

Ini harus menjadi informasi yang cukup untuk menyelesaikan kueri:

Mari kita buat data tiruannya

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

Sekarang meledakkan array menggunakan jsonb_array_elements dengan ordinalitas untuk mendapatkan indeks dan properti

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

Hasil dari query ini adalah:

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

Di sana Anda memiliki info yang diperlukan untuk mengambil sub elemen yang Anda butuhkan, serta semua indeks yang Anda butuhkan untuk kueri Anda.

Sekarang, untuk pengeditan terakhir, Anda sudah memiliki kueri yang Anda inginkan:

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

Di tempat Anda akan menggunakan id, karena itu adalah baris yang Anda minati, dan di indeks Anda mendapatkannya dari kueri. Jadi:

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;

Seperti yang Anda lihat, ini sangat buruk.

Saya akan merekomendasikan menggunakan pendekatan yang lebih sql, yaitu, memiliki fitur dalam tabel alih-alih di dalam json, fk yang menautkannya ke tabel Anda...Jika Anda benar-benar perlu menggunakan json, misalnya, karena domain sangat kompleks dan didefinisikan pada tingkat aplikasi dan sangat fleksibel. Maka saya akan merekomendasikan melakukan pembaruan di dalam kode aplikasi




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara beralih antara operasi yang diindeks dan tidak diindeks tergantung pada input?

  2. Bagaimana saya mendapatkan psycopg2 logging dari waktu eksekusi kueri?

  3. Mengapa kinerja kueri PostgresQL turun seiring waktu, tetapi dipulihkan saat membangun kembali indeks

  4. Kesalahan:EXDEV:tautan lintas perangkat tidak diizinkan, ganti nama '/tmp/ di Ubuntu 16.04 LTS

  5. Melakukan pembaruan besar menggunakan banyak tabel di PostgreSQL