Dit zou voldoende informatie moeten zijn om de zoekopdracht te voltooien:
Laten we de nepgegevens maken
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
}
]
}
]');
Ontplof nu de array met jsonb_array_elements met ordinaliteit om de index en de eigenschap te krijgen
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);
Het resultaat van deze zoekopdracht is:
1,1,1,"{""name"": ""feature1"", ""granted"": false}"
1,1,2,"{""name"": ""feature2"", ""granted"": true}"
Daar heb je de nodige informatie die je nodig hebt om de subelementen op te halen die je nodig hebt, evenals alle indexen die je nodig hebt voor je zoekopdracht.
Nu, bij de laatste bewerking, had je al de vraag die je wilde:
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}]}';
In de plaats waar je de id gaat gebruiken, want dat zijn de rijen waarin je geïnteresseerd bent, en in de indexen die je uit de query hebt gehaald. Dus:
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;
Zoals je kunt zien, wordt dit gemakkelijk erg smerig.
Ik raad aan om ofwel een meer sql-benadering te gebruiken, dat wil zeggen functies in een tabel te hebben in plaats van in een json, een fk die dat aan je tabel koppelt... Als je echt de json moet gebruiken, bijvoorbeeld omdat het domein is echt complex en gedefinieerd op applicatieniveau en zeer flexibel. Dan zou ik aanraden om de updates in de app-code te doen