Имеем Laravel 7 и PostgreSql 9.
Как-то я столкнулся с довольно простой задачей, мне нужно было обновить jsonb колонку данными из той же самой записи. Казалось бы, что тут может пойти не так? Однако у меня возникли некоторые трудности. Но как обычно это бывает трудности были от незнания. Поэтому в этой записи я расскажу, как я решил эту задачу.
Я хотел сделать это одним запросом, поэтому что это самый оптимальный вариант. Но я не смог найти способ. Из-за этого первым вариантом для меня было такое решение:
DB::table('users')
->select('id', 'name')
->whereNotNull('name')
->orderBy('id')
->chunk(200, function ($users) {
foreach ($users as $user) {
DB::table('users')
->where('id', $user->id)
->update([
'profile' => [
'title' => $user->name
]
]);
}
});
Но этот способ плох по разным причинам. Он слишком объемный, долговыполнимый и даёт довольно большую нагрузку при огромном количестве записей.
Затем я попытался использовать функцию jsonb_set. С помощью этого способа можно было бы решить проблему одним запросом, если бы это было скалярное значение, а не значение из другой колонки:
update users set profile = jsonb_set(profile, '{title}', '"name"') where name is not null;
Но это мне не подходит, т.к. мне не нужно вставлять строку.
Решение оказалось довольно простым — использовать функцию json_build_object. В итоге получилось вот такое решение:
update users set "profile" = json_build_object('title', "name")