postgresql - 对json对象的键/值查找

时间:2017-05-08 18:36:22

标签: sql json postgresql jsonb

运行Postgres 9.6。

所以我有这个键/值查找表,它建立了一个巨大的JSON对象的最深子值。给出了这种结构的表格:

CREATE TABLE myschema.file_items
(
    id integer NOT NULL DEFAULT nextval('file_items_id_seq'::regclass),
    file_id integer NOT NULL,
    key character varying[] COLLATE pg_catalog."default" NOT NULL,
    value character varying COLLATE pg_catalog."default",
    status character varying COLLATE pg_catalog."default",
    CONSTRAINT file_items_pkey PRIMARY KEY (id)
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;

ALTER TABLE verification.file_items
    OWNER to postgres;

insert into file_items (file_id, key, value, status)
values (1, '{"cogs","cog1","description"}', 'val1', 'approved');
insert into file_items (file_id, key, value, status)
values (1, '{"cogs","cog1","cost"}', '100', null);
insert into file_items (file_id, key, value, status)
values (1, '{"cogs","cog1","window"}', '[-200,500]', 'not verified');
insert into file_items (file_id, key, value, status)
values (1, '{"cogs","cog2","description"}', 'val2', 'approved');
insert into file_items (file_id, key, value, status)
values (1, '{"cogs","cog2","cost"}', '200', null);
insert into file_items (file_id, key, value, status)
values (1, '{"cogs","cog2","window"}', '[-300,500]', null);

insert into file_items (file_id, key, value, status)
values (1, '{"widgets","widget1","description"}', 'wid1', 'approved');
insert into file_items (file_id, key, value, status)
values (1, '{"widgets","widget1","cost"}', '100', 'approved');
insert into file_items (file_id, key, value, status)
values (1, '{"widgets","widget1","window"}', '[-200,500]', 'not verified');
insert into file_items (file_id, key, value, status)
values (1, '{"widgets","widget2","description"}', 'wid2', null);
insert into file_items (file_id, key, value, status)
values (1, '{"widgets","widget2","cost"}', '300', 'approved');
insert into file_items (file_id, key, value, status)
values (1, '{"widgets","widget2","window"}', '[-1000,700]', null);

我可以查询所有我的齿轮:

select *
from file_items
where 'cogs' = any(key)

我该如何对这个物体进行逆向工程?相反,我想以某种方式生成具有以下格式的json对象:

"cogs": {
    "cog1": {
        "description": "val1",
        "cost":100,
        "window":[-200,500]
    },
    "cog2": {
        "description": "val2",
        "cost":200,
        "window":[-300,500]
    }
}

请注意,我故意不想做一组cogs对象。它们是cogs对象的实际属性。这样做是因为我们可以拥有我们不知道所有属性的传入json对象,因此我们利用键/值映射表来动态识别这些属性值是什么(即,我们不&# 39;我们事先知道我们将拥有一个" cog67"对象,或者该对象会附加什么样的属性....)。

由于此查询最终将从Node.js包中触发(' pg'模块...),如果我无法通过查询重新创建json对象,我可能需要在javascript本身做到这一点。只是想知道是否有可能在数据库级别正确构建json对象并返回它,而不是查询一堆行并在服务器端代码中重新构造对象。

任何帮助将不胜感激!谢谢!

1 个答案:

答案 0 :(得分:2)

对两个聚合级别使用jsonb_object_agg()两次(jsonb_pretty()不必要,用于良好的输出):

select jsonb_pretty(jsonb_build_object(key, jsonb_object_agg(subkey, value)))
from (
    select key[1], key[2] as subkey, jsonb_object_agg(key[3], value) as value
    from file_items
    where 'cogs' = any(key)
    group by key[1], key[2]
    ) s
group by key;

            jsonb_pretty             
-------------------------------------
 {                                  +
     "cogs": {                      +
         "cog1": {                  +
             "cost": "100",         +
             "window": "[-200,500]",+
             "description": "val1"  +
         },                         +
         "cog2": {                  +
             "cost": "200",         +
             "window": "[-300,500]",+
             "description": "val2"  +
         }                          +
     }                              +
 }
(1 row)