【问题标题】:JSONB to Array Data TypeJSONB 转数组数据类型
【发布时间】:2019-05-20 15:19:56
【问题描述】:

我目前有一个带有列操作 (JSONB) 的表会话。

我能够使用array_to_jsonb(array value) 将数组从我的前端正确存储到我的数据库中。

我的数组(数组值)的结构是这样的:

var arrayStructure = [
    {name: 'email client', check: false},
    {name: 'send contract', check: false}
]

与我在 SO 上看到的关于修改 JSONB 或访问某些键的许多问题不同,我只对将整个 JSONB 数据转换回前端数组感兴趣。

我的临时解决方法是映射数组并在 Javascript 中使用 JSON.parse() 来重构数组中的每个对象。我不能在整个数组上使用 JSON.parse(),因为它会引发错误。

我正在寻找一个查询以将数组格式恢复为存储的 JSONB 数据类型。我见过 JSONB_SET、LATERAL 和 JSONB_ARRAY_ELEMENTS_TEXT。但不是以一种可以恢复适当阵列的方式。

开始为: JSONB 在名为会话的表中的操作列中

应返回:一个查询返回所有行,但将操作列 (JSONB) 转换回前端的数组:

select session_id, session_name, someFunction or lateral here(actions) from sessions

Screenshot of Sessions Table

我试过这样的查询:

SELECT 
   session_id, 
   actions::jsonb -> 'name' as name
FROM sessions;

然后返回 null 作为名称。我试过 ->> 来访问更深的层次,但这也不起作用。

这是正确查询结果的一半:

select session_id, jsonb_array_elements_text(actions)
from sessions
group by session_id;

这会导致(只注意 session_id 为 264 的结果): query result

现在我在自己的行中有对象:

 {"name": "some task", "check": "false} 

当我想要的操作栏是:

[ {name: "some task", check: false}, {name: "other task", check: true} ]

所以我需要进一步解析 JSON 并按 session_id 分组。我只是在努力构建一个这样做的子查询。

创建设置的步骤:

create table fakeSessions (
session_id serial primary key, 
name varchar(20), 
list jsonb
)

insert into fakeSessions(name, list)
VALUES(
'running',
'["{\"name\":\"inquired\",\"check\":false}", "{\"name\":\"sent online guide\",\"check\":false}", "{\"name\":\"booked!\",\"check\":false}"]'
)

insert into fakeSessions(name, list)
VALUES(
'snowboarding',
'["{\"name\":\"rental\",\"check\":false}", "{\"name\":\"booked ski passes\",\"check\":false}", "{\"name\":\"survey\",\"check\":false}"]'
)

我创建的最接近的查询:

with exports as (
    select jsonb_array_elements_text(actions)::jsonb as doc from sessions
)
select array_agg(doc) from
exports, sessions
group by session_id;

获取文本值,然后对返回的行应用聚合函数。只是无法让 select array_agg(doc) 按预期工作。很可能是因为我在那个地方需要不同的功能。

【问题讨论】:

  • 请提供一些 ddl / dml 以重现该问题。另外,显示您的预期输出和格式
  • 请展示表格和数据的样子。你有一个包含整个 jsonb 数组的单行吗?每个数组元素有一行吗?您是否有用于名称和检查的单列?
  • @S-Man,actions 列是 JSONB,它包含一个对象数组。每个对象中有 2 个键:名称和检查。 [ {name: 'some name' check: false} ]
  • @KaushikNayak,我附上了示例数据的屏幕截图以提供帮助。没有问题或错误消息。我只是无法在 DOCS 中找到一种使用 postgres 转换回数组而不在前端使用 JSON.parse() 的方法。
  • 我真的还是不明白。请添加一些示例数据(作为文本,以便我们可以复制到我们的工具中)和您的预期输出。我的理解是:您有一些带有数组的行,并且您想要合并这些数组。所以第 1 行有 [{name:a, check:t}, {name:b, check:f}] 和第 2 行有 [{name:c, check:t}] 并且你想要 [{name:a... }, {name:b,...}, {name:c,...}]?

标签: sql arrays json postgresql jsonb


【解决方案1】:

这有帮助吗?

demo:db<>fiddle

SELECT
    jsonb_agg(elem) 
FROM
    sessions, jsonb_array_elements(actions) as elem
  1. jsonb_array_elements()jsonb 数组扩展为一行,每个 jsonb 元素
  2. jsonb_agg() 将这些 jsonb 元素聚合成一个大数组。

【讨论】:

  • 你摇滚!通过构建这个,我能够获得正确的格式。感谢您提供惊人的反馈并与我一起解决这个问题。让我开心:)
  • 我刚刚获得了对这个问题/答案进行投票的能力。所以我很高兴能投出我的第一个赞成票! :)
【解决方案2】:

通过构建您的查询,我能够找到答案!太感谢了。得到预期结果的查询是这样的:

with exports as (
    select session_id, jsonb_array_elements_text(actions)::jsonb as doc from sessions
)
select session_id, jsonb_agg(doc) from exports
group by session_id;

获得元素后,我没有使用 jsonb_agg() 函数。获得确切格式的区别只是使用jsonb_array_elements_text::jsonb

【讨论】:

  • 嗯 json_array_element_text 将json元素转换为纯文本。然后你将它转换回json。这似乎不合逻辑。 postgres 的 json 引擎是高性能的。如果将对象转换为介于两者之间的其他类型,则可能会损失很多性能。
猜你喜欢
  • 1970-01-01
  • 2020-07-01
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
  • 1970-01-01
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多