Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Globally replace in Postgres JSONB field

I need to globally replace a particular string that occurs multiple places in a nested JSON structure, thats stored as jsonb in a postgres table. For example:

{
  "location": "tmp/config",
  "alternate_location": {
    "name": "config",
    "location": "tmp/config"
  }
}

...should become:

{
  "location": "tmp/new_config",
  "alternate_location": {
    "name": "config",
    "location": "tmp/new_config"
  }
}

I've tried:

UPDATE files SET meta_data = to_json(replace(data::TEXT, 'tmp/config', 'tmp/new_config'));

Unfortunately this results in malformed JSON, with triple escaped quotes.

Any ideas how to do this?

like image 977
crowhoplaminar Avatar asked Dec 08 '17 19:12

crowhoplaminar


Video Answer


2 Answers

Use a simple cast to jsonb instead of to_json(), e.g.:

with files(meta_data) as (
values(
'{
  "location": "tmp/config",
  "alternate_location": {
    "name": "config",
    "location": "tmp/config"
  }
}'::jsonb)
)

select replace(meta_data::text, 'tmp/config', 'tmp/new_config')::jsonb
from files;

                                                replace                                                 
--------------------------------------------------------------------------------------------------------
 {"location": "tmp/new_config", "alternate_location": {"name": "config", "location": "tmp/new_config"}}
(1 row)
like image 56
klin Avatar answered Oct 02 '22 05:10

klin


Use update:

UPDATE files SET meta_data = replace(data::TEXT, 'tmp/config', 'tmp/new_config')::jsonb;
like image 21
Sajad Abdollahi Avatar answered Oct 02 '22 05:10

Sajad Abdollahi