从 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
我的数据库中有一个 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