これは、クエリを完了するのに十分な情報である必要があります:
模擬データを作成しましょう
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
}
]
}
]');
次に、通常のjsonb_array_elementsを使用して配列を分解し、インデックスとプロパティを取得します
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);
このクエリの結果は次のとおりです。
1,1,1,"{""name"": ""feature1"", ""granted"": false}"
1,1,2,"{""name"": ""feature2"", ""granted"": true}"
そこには、必要なサブ要素をフェッチするために必要な情報と、クエリに必要なすべてのインデックスがあります。
さて、最後の編集まで、あなたはすでにあなたが望むクエリを持っていました:
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}]}';
idを使用する場所では、これらは関心のある行であり、インデックスではクエリから取得したためです。だから:
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;
ご覧のとおり、これは簡単に非常に厄介になります。
よりSQLのアプローチを使用することをお勧めします。つまり、json内ではなくテーブル内に機能を配置し、fkをテーブルにリンクします...たとえば、ドメインのためにjsonを本当に使用する必要がある場合非常に複雑で、アプリケーションレベルで定義されており、非常に柔軟性があります。次に、アプリコード内で更新を行うことをお勧めします