很难合并 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. 在 keyvalue 列中使用 jsonb_array_elements() 和 select json 值 fieldvalue ]:

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 从列 sessionemail 构建的对象,并构建包含所有对象的 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)