简体   繁体   English

使用 postgres 12.10 更新 jsonb 列中的嵌套数组元素

[英]Updating a nested array element in a jsonb column with postgres 12.10

I am trying to update a record in an array.我正在尝试更新数组中的记录。 The table is participant and the column is activities with the shape:表是participant ,列是activities ,形状为:

{
  enrolled: [{
    sport: {
      id: 1,
      name: 'soccer'
    }
  }, {
    sport: {
      id: 2,
      name: 'hockey'
    }
  }]
}

I'd like to run a query that says,我想运行一个查询,说,

If activities[*].enrolled.sport == 1, add some JSON blob for the registered day如果活动[*].enrolled.sport == 1,则为注册日添加一些 JSON blob

registered: {
  day: 12,
  month: 'Aug'
}

The resulting object would be:生成的 object 将是:

{
  enrolled: [{
    sport: {
      id: 1,
      name: 'soccer'
    },
    registered: {
      day: 12
      month: 'Aug'
    }
  }, {
    sport: {
      id: 2,
      name: 'hockey'
    }
  }]
}

I've tried the following but it replaces the entire column with the added object:(我尝试了以下方法,但它用添加的 object 替换了整个列:(

set activities = (
    select jsonb_agg(jsonb_set(sports, '{registered}', '{"day": 12, "month": "Aug"}', true))
    from jsonb_array_elements(activities::jsonb -> 'enrolled') sports
)
where activities::jsonb -> 'enrolled' @? '$.sport.id ? (@ == 1)';

I am afraid that you have to rebuild the whole activities object.恐怕你必须重建整个activities object。
Unrelated but I think that this is a poor data design.无关,但我认为这是一个糟糕的数据设计。 Your examples are far from valid JSON.您的示例远非有效的 JSON。

update participant set activities = 
(
 select jsonb_build_object
 (
  'enrolled', 
  (jsonb_agg(case when j->'sport'->>'id' = '1' then j||YOUR_JSONB_BLOB else j end))
 ) 
 from jsonb_array_elements(activities->'enrolled') j 
)
where activities @> '{"enrolled":[{"sport":{"id":1}}]}';

Here is an illustration with your example这是您的示例的插图

select jsonb_build_object
 (
  'enrolled', 
  (jsonb_agg(case when j->'sport'->>'id' = '1' then j||'{"registered":{"day":12,"month":"Aug"}}' else j end))
 ) 
from jsonb_array_elements('
 {
 "enrolled": 
 [
    { "sport": { "id": 1, "name": "soccer"}},
    { "sport": { "id": 2, "name": "hockey"}}
 ]
 }'::jsonb->'enrolled') j;

Result:结果:

{
  "enrolled": [
    {
      "sport": {
        "id": 1,
        "name": "soccer"
      },
      "registered": {
        "day": 12,
        "month": "Aug"
      }
    },
    {
      "sport": {
        "id": 2,
        "name": "hockey"
      }
    }
  ]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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