将Go字符串转换为Postgres中jsonb_set的jsonb参数。

huangapple go评论116阅读模式
英文:

Query Go string into a jsonb argument for jsonb_set in Postgres

问题

我正在使用Go和"github.com/jackc/pgx/v4/pgxpool"

我的表中有一个字段是json类型,我需要在一个查询中更新两个键。

第一个问题是同时更新多个键,但我认为使用嵌套的jsonb_set函数可以正常工作。

更大的问题是在这种情况下参数替换的工作原理。

  1. UPDATE my_table
  2. SET
  3. first_column=$2,
  4. json_column = JSONB_SET(JSONB_SET(
  5. json_column::jsonb,
  6. '{first_key_name}',
  7. $3,
  8. true),
  9. '{second_key_name}',
  10. $4,
  11. true),
  12. updated_at = now() at time zone 'utc'
  13. WHERE id=$1

然而,这会导致invalid input syntax for type json错误。在参数($3,$4)周围/之后添加to_jsonb()::jsonb也没有帮助。

下面是如何使用pgx库将参数传递给查询的示例。两个键值都是string类型。

  1. err := pool.QueryRow(ctx, myQuery,
  2. id,
  3. first_column,
  4. first_key_value,
  5. second_key_value
  6. ).
  7. Scan(...)

经过一些尝试,似乎使其工作的一种方法是使用jsonb_build_array然后获取第0个元素。这看起来非常难以阅读,我几乎确定一定有更简单的方法来实现这个目标。

  1. UPDATE my_table
  2. SET
  3. first_column=$2,
  4. json_column = JSONB_SET(JSONB_SET(
  5. json_column::jsonb,
  6. '{first_key_name}',
  7. jsonb_array_element(jsonb_build_array($3::text), 0),
  8. true),
  9. '{second_key_name}',
  10. jsonb_array_element(jsonb_build_array($4::text), 0),
  11. true),
  12. updated_at = now() at time zone 'utc'
  13. WHERE id=$1
英文:

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.

  1. UPDATE my_table
  2. SET
  3. first_column=$2,
  4. json_column = JSONB_SET(JSONB_SET(
  5. json_column::jsonb,
  6. '{first_key_name}',
  7. $3,
  8. true),
  9. '{second_key_name}',
  10. $4,
  11. true),
  12. updated_at = now() at time zone 'utc'
  13. 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.

  1. err := pool.QueryRow(ctx, myQuery,
  2. id,
  3. first_column,
  4. first_key_value,
  5. second_key_value
  6. ).
  7. 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.

  1. UPDATE my_table
  2. SET
  3. first_column=$2,
  4. json_column = JSONB_SET(JSONB_SET(
  5. json_column::jsonb,
  6. '{first_key_name}',
  7. jsonb_array_element(jsonb_build_array($3::text), 0),
  8. true),
  9. '{second_key_name}',
  10. jsonb_array_element(jsonb_build_array($4::text), 0),
  11. true),
  12. updated_at = now() at time zone 'utc'
  13. WHERE id=$1

答案1

得分: 1

你可以在这里使用||运算符。
最初,假设记录如下所示:

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

更新后:

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

请记住,如果找到顶层键,则替换它,否则创建一个新键。在||运算符的右侧使用jsonb_build_object来创建JSON对象。

英文:

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

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

After update

  1. update dummy set j=j::jsonb||'{"a": "new_value"}
  2. {"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

huangapple
  • 本文由 发表于 2022年5月17日 18:33:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/72272460.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定