Postgres 扩展对象数组 (jsonb)

发布于 2025-01-11 18:14:15 字数 1235 浏览 5 评论 0原文

我有一个 postgres 表,我想在其中扩展 jsonb 列。

该表(称为“runs”)将每个参与者视为一行,其中 jsonb 列保存他们的实验数据。

id |data         |
---|-------------|
id1|[{}, {}]     |
id2|[{}, {}, {}] |

jsonb 列始终是一个包含未知数量对象的数组,其中每个对象都有未知数量的任意键。

[
  {
    "rt": 3698,
    "phase": "questionnaire",
    "question": 1
  },
  {
    "rt": 3698,
    "phase": "forced-choice",
    "choice": 0,
    "options": ["red", "blue"]
  }
]

我想 (1) 展开 jsonb 列,以便每个对象都是一行:

id |rt    | phase         | question | choice | options        |
---|------| ------------- | -------- | ------ | -------------- |
id1| 3698 | questionnaire | 1        |        |                |
id1| 5467 | choice        |          | 0      | ["red", "blue] |

或 (2) 将行中的其他列映射到 jsonb 数组(此处为“id”键):

[
  { 
    "id": "id1",
    "rt": 3698,
    "phase": "questionnaire",
    "question": 1
  },
  {
    "id": "id1",
    "rt": 3698,
    "phase": "forced-choice",
    "choice": 0,
    "options": ["red", "blue"]
  }
]

事实上,对象的数量,每个对象的键数量,以及键本身是先验未知的,这确实让我很难完成这个任务。也许是这样的,但这是不对的......

SELECT id, x.*
FROM
 runs_table, 
 jsonb_populate_recordset(null:runs_table, data) x

I have a postgres table in which I want to expand a jsonb column.

The table (called runs) has each participant as a single row, with the jsonb column holding their experiment data.

id |data         |
---|-------------|
id1|[{}, {}]     |
id2|[{}, {}, {}] |

The jsonb column is always an array with an unknown number of objects, where each object has an unknown number of arbitrary keys.

[
  {
    "rt": 3698,
    "phase": "questionnaire",
    "question": 1
  },
  {
    "rt": 3698,
    "phase": "forced-choice",
    "choice": 0,
    "options": ["red", "blue"]
  }
]

I would like to either (1) expand the jsonb column so each object is a row:

id |rt    | phase         | question | choice | options        |
---|------| ------------- | -------- | ------ | -------------- |
id1| 3698 | questionnaire | 1        |        |                |
id1| 5467 | choice        |          | 0      | ["red", "blue] |

OR (2) map the other columns in the row to the jsonb array (here the "id" key):

[
  { 
    "id": "id1",
    "rt": 3698,
    "phase": "questionnaire",
    "question": 1
  },
  {
    "id": "id1",
    "rt": 3698,
    "phase": "forced-choice",
    "choice": 0,
    "options": ["red", "blue"]
  }
]

The fact that the number of objects, the number of keys per object, and the keys themselves are unknown a priori is really stumping me on how to accomplish this. Maybe something like this, but this isn't right...

SELECT id, x.*
FROM
 runs_table, 
 jsonb_populate_recordset(null:runs_table, data) x

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

伴我老 2025-01-18 18:14:15

PostgreSQL 有许多 JSON 函数。首先,您必须从“JSONB”中提取键和值。之后,您可以使用 Postgres jsonb_typeof(jsonb) 函数获取值的类型。我为您编写了两个示例:

-- sample 1 
select * 
from jsonb_array_elements(
    '[
      { 
        "id": "id1",
        "rt": 3698,
        "phase": "questionnaire",
        "question": 1
      },
      {
        "id": "id1",
        "rt": 3698,
        "phase": "forced-choice",
        "choice": 0,
        "options": ["red", "blue"]
      }
    ]'::jsonb 
) t1 (json_data)
cross join jsonb_each(t1.json_data) t2(js_key, js_value)
where jsonb_typeof(t2.js_value::jsonb) = 'array' 

-- sample 2
select *
from jsonb_array_elements(
    '[
      { 
        "id": "id1",
        "rt": 3698,
        "phase": "questionnaire",
        "question": 1
      },
      {
        "id": "id1",
        "rt": 3698,
        "phase": "forced-choice",
        "choice": 0,
        "options": ["red", "blue"]
      }
    ]'::jsonb 
) t1 (json_data)
where jsonb_typeof((t1.json_data->'options')::jsonb) = 'array' 

示例 1: 此查询将从 JSONB 中提取所有键和值,然后设置过滤以仅显示数组类型的值。

示例 2:如果您知道哪些键可以是数组类型,请使用此查询。

PostgreSQL has a many JSON functions. Firstly you must extract keys and values from 'JSONB'. After then you can get the type of values using Postgres jsonb_typeof(jsonb) function. I wrote two samples for you:

-- sample 1 
select * 
from jsonb_array_elements(
    '[
      { 
        "id": "id1",
        "rt": 3698,
        "phase": "questionnaire",
        "question": 1
      },
      {
        "id": "id1",
        "rt": 3698,
        "phase": "forced-choice",
        "choice": 0,
        "options": ["red", "blue"]
      }
    ]'::jsonb 
) t1 (json_data)
cross join jsonb_each(t1.json_data) t2(js_key, js_value)
where jsonb_typeof(t2.js_value::jsonb) = 'array' 

-- sample 2
select *
from jsonb_array_elements(
    '[
      { 
        "id": "id1",
        "rt": 3698,
        "phase": "questionnaire",
        "question": 1
      },
      {
        "id": "id1",
        "rt": 3698,
        "phase": "forced-choice",
        "choice": 0,
        "options": ["red", "blue"]
      }
    ]'::jsonb 
) t1 (json_data)
where jsonb_typeof((t1.json_data->'options')::jsonb) = 'array' 

Sample 1: This Query will extract all keys and values from JSONB and after then will be set filtering for showing only array type of values.

Sample 2: Use this query if you know which keys can be array types.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文