从 Postgresql 数据库中查询包含嵌套 JSON 的简化 JSONB 形式 JSONB 列?

Query simplified JSONB form JSONB column containing nested JSON from a Postgresql database?

我的数据库中有一个 JSONB 列,其中包含嵌套的 JSON。我需要查询此列,但我想保留 JSON 结构并且只删除不必要的键值。 假设这是数据库中的示例记录:

{
  "id": 1,
  "foo": "bar",
  "something": "anything",
  "something_else": "anything_else",
  "video": [
    {
      "id": 1,
      "type": "slow",
      "width": 700,
      "height": 900
    },
    {
      "id": 2,
      "type": "medium",
      "width": 900,
      "height": 100
    },
    {
      "id": 3,
      "type": "fast",
      "width": 700,
      "height": 900
    }
  ],
  "image": {
    "candidates": [
      {
        "width": 480,
        "height": 600,
        "scans_profile": "e35"
      },
      {
        "width": 480,
        "height": 600,
        "scans_profile": "e35"
      }
    ]
  }
}

我需要得到:

{
  "id": 1,
  "foo": "bar",
  "video": [
    {
      "id": 1,
      "width": 700,
      "height": 900
    },
    {
      "id": 2,
      "width": 900,
      "height": 100
    },
    {
      "id": 3,
      "width": 700,
      "height": 900
    }
  ],
  "image": {
    "candidates": [
      {
        "scans_profile": "e35"
      },
      {
        "scans_profile": "e35"
      }
    ]
  }
}

有没有优雅、简单的方法来做到这一点?或者有什么办法吗?

我正在使用 postgres 13.3

如果您的源数据总是具有相同的格式,您可以删除不需要的路径。这将起作用,因为您正在过滤掉特定的键并且不进行其他转换。如果源可以有不同数量的键或在编写此查询时未知的可变数组长度,这将失败,因为您不会删除那些其他未知路径。

即如果顶级键总是 [id, key, something, something_else, video, image]

其中 video 始终是 json 个对象的数组,键 [id, type, width, height] 的长度为 3

image 是一个具有一个键的对象 candidates 这是一个长度为 2 的对象数组,具有键 [width, height, scans_profile] 然后你可以写如下:

SELECT
my_json_column 
  #- '{something}'
  #- '{something_else}'
  #- '{video,0,type}'
  #- '{video,1,type}'
  #- '{video,2,type}'
  #- '{image,candidates,0,width}'
  #- '{image,candidates,1,width}'
  #- '{image,candidates,0,height}'
  #- '{image,candidates,1,height}'
AS my_new_json_column
FROM my_table

这里是 fiddle:https://dbfiddle.uk/?rdbms=postgres_13&fiddle=508e6b864ff811289b4610c4c2380df8

否则,您唯一的选择是建立一个新的 jsonb 对象

SELECT
  jsonb_build_object(
    'id', my_json_column->'id',
    'foo', my_json_column->'foo',
    'video', video.video,
    'image', jsonb_build_object('candidates', image_candidates.image_candidates)
  ) AS my_new_json_column
FROM my_table
LEFT JOIN LATERAL (
  SELECT jsonb_agg(jsonb_build_object(
      'id', y->'id', 
      'width', y->'width', 
      'height', y->'height'
  )) video
  FROM jsonb_path_query(my_json_column, '$.video[*]') v(y)
) video ON true
LEFT JOIN LATERAL (
  SELECT jsonb_agg(jsonb_build_object(
      'scans_profile', y->'scans_profile'
    )) image_candidates
  FROM jsonb_path_query(my_json_column, '$.image.candidates[*]') v(y)
) image_candidates ON true