简体   繁体   中英

Query Go string into a jsonb argument for jsonb_set in Postgres

I am using Go and "github.com/jackc/pgx/v4/pgxpool" .

One of the fields in my table has json and I need to update two keys in one query.

The first problem was to update several keys at once but I think it works fine now with a nested jsonb_set .

A bigger problem is how parameter substitution works in this case.

UPDATE my_table
    SET 
        first_column=$2,
        json_column = JSONB_SET(JSONB_SET(
                     json_column::jsonb, 
                    '{first_key_name}', 
                     $3,
                     true), 
                '{second_key_name}', 
                $4,
                true),
        updated_at  = now() at time zone 'utc'
    WHERE id=$1

This yields, however, the invalid input syntax for type json error. Adding either to_jsonb() or ::jsonb around/after the parameters ($3, $4) didn't help.

Below is how the pgx library is used to pass the arguments to the query. Both key value are of string type.

err := pool.QueryRow(ctx, myQuery,
        id,
        first_column,
        first_key_value,
        second_key_value
    ).
        Scan(...)

After some experimenting, it seems that one way to make it work is to use jsonb_build_array and then get the 0-th item. That looks totally unreadable and I am almost sure there must be a simpler way to achieve this.

UPDATE my_table
    SET 
        first_column=$2,
        json_column = JSONB_SET(JSONB_SET(
                     json_column::jsonb, 
                    '{first_key_name}', 
                     jsonb_array_element(jsonb_build_array($3::text), 0), 
                     true), 
                '{second_key_name}', 
                jsonb_array_element(jsonb_build_array($4::text), 0),
                true),
        updated_at  = now() at time zone 'utc'
    WHERE id=$1

You could use || operator here. Initially lets say the record look like this:

{"a":"b","key2":"value2"}

After update

update dummy set j=j::jsonb||'{"a": "new_value"}
{"a":"new_value","key2":"value2"}

Remember it replaces top level keys if found otherwise create a new key. use jsonb_build_object to create json object on right side of ||operator

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM