很难合并 jsonb 对象数组和列
Difficult merging of jsonb object array and columns
我有一个table
Visitor: (id, signup_up, sessions, email, custom_fields)
其中 custom_fields
是一个 jsonb 数组 JSON 形式的对象
CustomField: ( field, value )
示例:(domain, www.somedomain.com)
我想获取 signed_up, sessions, email
列及其值,以及 custom_fields
数组中的 CustomField
json 对象,并将它们合并到名为的第三个字段中data
使用相同的 CustomField
结构,即。每个条目的形式为 field: value
.
例子
鉴于这些行
id | sessions | email | custom_fields
---------------------------------------------------------------
1 | 3 | test@gmail.com [{ field: domain, value: "www.hello.com" }, { field: type, value: "Customer" }]
---------------------------------------------------------------
2 | 5 | another@gmail.com [{ field: domain, value: "www.other.com" }, { field: type, value: "Customer" }]
我想得到
id | fields
-----------------------
1 | [{sessions: 3, email: test@gmail.com, domain: "www.hello.com", type: "Customer"}]
----------------------
2 | [{sessions: 5, email: another@gmail.com, domain: "www.other.com", type: "Customer"}]
知道如何实现吗?
非常感谢任何帮助
示例数据(这应该是问题的一部分,而不是答案;注意正确的 json 语法):
create table visitor (id int, sessions int, email text, custom_fields jsonb);
insert into visitor values
(1, 3, 'test@gmail.com', '[{"field": "domain", "value": "www.hello.com" }, {"field": "type", "value": "Customer"}]'),
(2, 5, 'another@gmail.com', '[{"field": "domain", "value": "www.other.com" }, {"field": "type", "value": "Customer"}]');
提示 1. 在 key
和 value
列中使用 jsonb_array_elements()
和 select json 值 field
和 value
]:
select id, sessions, email, elem->>'field' as key, elem->>'value' as value
from visitor, jsonb_array_elements(custom_fields) elem;
id | sessions | email | key | value
----+----------+-------------------+--------+---------------
1 | 3 | test@gmail.com | domain | www.hello.com
1 | 3 | test@gmail.com | type | Customer
2 | 5 | another@gmail.com | domain | www.other.com
2 | 5 | another@gmail.com | type | Customer
(4 rows)
技巧 2. 使用 jsonb_object_agg()
将这些对 (key, value
) 聚合成一个 json 对象:
select
id,
jsonb_object_agg(key, value)
from (
select id, sessions, email, elem->>'field' as key, elem->>'value' as value
from visitor, jsonb_array_elements(custom_fields) elem
) s
group by id, sessions, email
order by id;
id | jsonb_object_agg
----+-------------------------------------------------
1 | {"type": "Customer", "domain": "www.hello.com"}
2 | {"type": "Customer", "domain": "www.other.com"}
(2 rows)
最终查询。添加(连接)json 从列 session
和 email
构建的对象,并构建包含所有对象的 json 数组:
select
id,
json_build_array(
jsonb_object_agg(key, value) ||
jsonb_build_object('sessions', sessions, 'email', email)
) as fields
from (
select id, sessions, email, elem->>'field' as key, elem->>'value' as value
from visitor, jsonb_array_elements(custom_fields) elem
) s
group by id, sessions, email
order by id;
id | fields
----+------------------------------------------------------------------------------------------------
1 | [{"type": "Customer", "email": "test@gmail.com", "domain": "www.hello.com", "sessions": 3}]
2 | [{"type": "Customer", "email": "another@gmail.com", "domain": "www.other.com", "sessions": 5}]
(2 rows)
另一个提示(或技巧):
select '{"a": null}'::jsonb || '{"a": 1}'::jsonb;
?column?
----------
{"a": 1}
(1 row)
我有一个table
Visitor: (id, signup_up, sessions, email, custom_fields)
其中 custom_fields
是一个 jsonb 数组 JSON 形式的对象
CustomField: ( field, value )
示例:(domain, www.somedomain.com)
我想获取 signed_up, sessions, email
列及其值,以及 custom_fields
数组中的 CustomField
json 对象,并将它们合并到名为的第三个字段中data
使用相同的 CustomField
结构,即。每个条目的形式为 field: value
.
例子
鉴于这些行
id | sessions | email | custom_fields
---------------------------------------------------------------
1 | 3 | test@gmail.com [{ field: domain, value: "www.hello.com" }, { field: type, value: "Customer" }]
---------------------------------------------------------------
2 | 5 | another@gmail.com [{ field: domain, value: "www.other.com" }, { field: type, value: "Customer" }]
我想得到
id | fields
-----------------------
1 | [{sessions: 3, email: test@gmail.com, domain: "www.hello.com", type: "Customer"}]
----------------------
2 | [{sessions: 5, email: another@gmail.com, domain: "www.other.com", type: "Customer"}]
知道如何实现吗?
非常感谢任何帮助
示例数据(这应该是问题的一部分,而不是答案;注意正确的 json 语法):
create table visitor (id int, sessions int, email text, custom_fields jsonb);
insert into visitor values
(1, 3, 'test@gmail.com', '[{"field": "domain", "value": "www.hello.com" }, {"field": "type", "value": "Customer"}]'),
(2, 5, 'another@gmail.com', '[{"field": "domain", "value": "www.other.com" }, {"field": "type", "value": "Customer"}]');
提示 1. 在 key
和 value
列中使用 jsonb_array_elements()
和 select json 值 field
和 value
]:
select id, sessions, email, elem->>'field' as key, elem->>'value' as value
from visitor, jsonb_array_elements(custom_fields) elem;
id | sessions | email | key | value
----+----------+-------------------+--------+---------------
1 | 3 | test@gmail.com | domain | www.hello.com
1 | 3 | test@gmail.com | type | Customer
2 | 5 | another@gmail.com | domain | www.other.com
2 | 5 | another@gmail.com | type | Customer
(4 rows)
技巧 2. 使用 jsonb_object_agg()
将这些对 (key, value
) 聚合成一个 json 对象:
select
id,
jsonb_object_agg(key, value)
from (
select id, sessions, email, elem->>'field' as key, elem->>'value' as value
from visitor, jsonb_array_elements(custom_fields) elem
) s
group by id, sessions, email
order by id;
id | jsonb_object_agg
----+-------------------------------------------------
1 | {"type": "Customer", "domain": "www.hello.com"}
2 | {"type": "Customer", "domain": "www.other.com"}
(2 rows)
最终查询。添加(连接)json 从列 session
和 email
构建的对象,并构建包含所有对象的 json 数组:
select
id,
json_build_array(
jsonb_object_agg(key, value) ||
jsonb_build_object('sessions', sessions, 'email', email)
) as fields
from (
select id, sessions, email, elem->>'field' as key, elem->>'value' as value
from visitor, jsonb_array_elements(custom_fields) elem
) s
group by id, sessions, email
order by id;
id | fields
----+------------------------------------------------------------------------------------------------
1 | [{"type": "Customer", "email": "test@gmail.com", "domain": "www.hello.com", "sessions": 3}]
2 | [{"type": "Customer", "email": "another@gmail.com", "domain": "www.other.com", "sessions": 5}]
(2 rows)
另一个提示(或技巧):
select '{"a": null}'::jsonb || '{"a": 1}'::jsonb;
?column?
----------
{"a": 1}
(1 row)