如何使用postgresql中的父级更新JSONB对象

时间:2017-11-13 18:19:37

标签: json postgresql jsonb

我的数据库包含一个包含列foo的表id和一个包含以下数据的列data

{
   "startDate":"2017-07-04",
   "endDate":"2017-07-10",
   "notDelegated":false,
   "sold":false,
   "disableRanking":false,
   "type":"PERIOD"
}

我想用父rangeData更新此数据并提取type属性,如下所示:

{
   "rangeData": {
       "startDate":"2017-07-04",
       "endDate":"2017-07-10",
       "notDelegated":false,
       "sold":false,
       "disableRanking":false
   },
   "type":"PERIOD"
}

我尝试使用JSON运算符做了很多事情。

感谢您的回答。

2 个答案:

答案 0 :(得分:1)

使用函数jsonb_build_object()并删除运算符:

update foo
set data = jsonb_build_object('rangeData', data- 'type', 'type', data->'type');

在上面的函数调用中,您将创建一个包含两个元素的json对象:

key          value
-------------------------
'rangeData'  data- 'type'   json object 'data' from which the key 'type' was removed
'type'       data->'type'   value of 'type' element of json object 'data'

SqlFiddle

答案 1 :(得分:0)

您可以使用jsonb_set(target jsonb, path text[], new_value jsonb[, create_missing boolean])(请参阅the docs)。

它不是很漂亮,但是我这样做了(你可以自己运行SQLFiddle我自己运行):

SELECT 
  jsonb_set(
    (final.range_data):: jsonb, 
    '{type}', 
    to_jsonb(final.type)
  ) 
FROM 
  (
    SELECT 
      jsonb_set(
        jsonb '{}', '{rangeData}', fields.range_data
      ) AS range_data, 
      fields.type AS type 
    FROM 
      (
        SELECT 
          data.jsonb - 'type' AS range_data, 
          data.jsonb ->> 'type' AS type 
        FROM 
          (
            SELECT 
              '{"startDate":"2017-07-04","endDate":"2017-07-10","notDelegated":false,"sold":false,"disableRanking":false,"type":"PERIOD"}' :: jsonb
          ) data
      ) fields
  ) final;

这将为您提供以下的jsonb输出:

{"rangeData": {"startDate":"2017-07-04","endDate":"2017-07-10","notDelegated":false,"sold":false,"disableRanking":false},"type":"PERIOD"}

所以你最终会做类似的事情:

UPDATE 
  foo 
SET 
  data = (
    SELECT 
      jsonb_set(
        (final.range_data):: jsonb, 
        '{type}', 
        to_jsonb(final.type)
      ) 
    FROM 
      (
        SELECT 
          jsonb_set(
            jsonb '{}', '{rangeData}', fields.range_data
          ) AS range_data, 
          fields.type AS type 
        FROM 
          (
            SELECT 
              data.jsonb - 'type' AS range_data, 
              data.jsonb ->> 'type' AS type 
            FROM 
              (
                SELECT 
                  foo.data
              ) data
          ) fields
      ) final
  );

我没有运行最终的UPDATE查询,但我确实运行了天真的SELECT语句,它按预期输出了我的输出。

另外,请注意,我是SQL的新手(特别是jsonb的东西),所以我相信会有更高性能和/或更正确的“jsonb-like”方式来做到这一点。取决于您的用例(如果是一次性迁移,或者如果您需要在每次实时阅读中执行此操作等)。