PostgreSQL:分页JSONB数据

时间:2019-03-10 21:48:48

标签: postgresql

这可能是远景,但是有什么方法可以通过查询限制JSONB数据?

我们正在调查MongoDB与PostgreSQL JSONB之间的差异,这可能是一个关键因素。

1 个答案:

答案 0 :(得分:1)

我同时使用了MongoDB和PostgreSQL(使用JSONB)和IMO,PostgreSQL赢得了90%的时间。

这是因为现实生活中的大多数数据本质上都是关系型的,而PostgreSQL提供了两全其美的优势。它是一个功能强大的关系数据库,但在需要时也具有JSONB的灵活性(例如JSON对于非结构化数据而言可能是完美的)。

它的劣势是巨大的(咳嗽)-MongoDB可以赢得胜利,例如当有大量无限制关系的原始JSON数据(或可以轻松转换为JSON的数据)时。

可以通过以下示例很好地说明PostgreSQL JSONB的功能:-

让我们按如下方式创建表(t):-

create table t (
    id serial primary key, 
    data jsonb); 

...带有一些演示数据...


insert into t (id, data) 
       values (1, '[{"name": "A", "age": 20},
                    {"name": "B", "age": 21},
                    {"name": "C", "age": 22},
                    {"name": "D", "age": 23},
                    {"name": "E", "age": 24},
                    {"name": "F", "age": 25},
                    {"name": "G", "age": 26}]'),
              (2, '[{"name": "H", "age": 27},
                    {"name": "I", "age": 28},
                    {"name": "J", "age": 29},
                    {"name": "K", "age": 30},
                    {"name": "L", "age": 31}]'),
              (3, '[{"name": "M", "age": 32},
                    {"name": "N", "age": 33},
                    {"name": "O", "age": 34},
                    {"name": "P", "age": 35},
                    {"name": "Q", "age": 36}]');

1。简单选择

如果我们仅从t中选择全部,我们将在data列中获得3行并带有JSONB数组。

select * 
  from t;  

----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 id | data
----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  1 | [{"age": 20, "name": "A"}, {"age": 21, "name": "B"}, {"age": 22, "name": "C"}, {"age": 23, "name": "D"}, {"age": 24, "name": "E"}, {"age": 25, "name": "F"}, {"age": 26, "name": "G"}]
  2 | [{"age": 27, "name": "H"}, {"age": 28, "name": "I"}, {"age": 29, "name": "J"}, {"age": 30, "name": "K"}, {"age": 31, "name": "L"}]
  3 | [{"age": 32, "name": "M"}, {"age": 33, "name": "N"}, {"age": 34, "name": "O"}, {"age": 35, "name": "P"}, {"age": 36, "name": "Q"}]
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2。选择+嵌套

然后我们可以使用data函数在jsonb_array_elements列中“取消嵌套” JSONB数组-这将返回17行iddata JSONB对象。

select id, 
       jsonb_array_elements(data) 
  from t;

----+--------------------------
 id | data
----+--------------------------
  1 | {"age": 20, "name": "A"}
  1 | {"age": 21, "name": "B"}
  1 | {"age": 22, "name": "C"}
  1 | {"age": 23, "name": "D"}
  1 | {"age": 24, "name": "E"}
  1 | {"age": 25, "name": "F"}
  1 | {"age": 26, "name": "G"}
  2 | {"age": 27, "name": "H"}
  2 | {"age": 28, "name": "I"}
  2 | {"age": 29, "name": "J"}
  2 | {"age": 30, "name": "K"}
  2 | {"age": 31, "name": "L"}
  3 | {"age": 32, "name": "M"}
  3 | {"age": 33, "name": "N"}
  3 | {"age": 34, "name": "O"}
  3 | {"age": 35, "name": "P"}
  3 | {"age": 36, "name": "Q"}
-------------------------------

3。选择+嵌套+分页

然后我们可以对上面的上一个“未嵌套”查询进行分页:-

select id, 
       jsonb_array_elements(data) 
  from t 
 limit 5; -- return 1st 5 

----+---------------------------
 id | data
----+---------------------------
  1 | {"age": 20, "name": "A"}
  1 | {"age": 21, "name": "B"}
  1 | {"age": 22, "name": "C"}
  1 | {"age": 23, "name": "D"}
  1 | {"age": 24, "name": "E"}
--------------------------------

select id, 
       jsonb_array_elements(data) 
  from t 
 limit 5 offset 5; -- return next 5

----+---------------------------
 id | data
----+---------------------------
  1 | {"age": 25, "name": "F"}
  1 | {"age": 26, "name": "G"}
  2 | {"age": 27, "name": "H"}
  2 | {"age": 28, "name": "I"}
  2 | {"age": 29, "name": "J"}
--------------------------------

4。选择+取消嵌套+分页+重新嵌套

我们可以进一步迈出这一步,并且可以再次按id进行分组,并使用jsonb_agg函数将JSON放回数组中:-

with t_unnested as (
    select id, 
           jsonb_array_elements(data) as data
      from t 
     limit 5 offset 5
)
select id, jsonb_agg (data) 
  from t_unnested
 group by id;

----+--------------------------------------------------------------------------------
 id | data
----+--------------------------------------------------------------------------------
  1 | [{"age": 25, "name": "F"}, {"age": 26, "name": "G"}]
  2 | [{"age": 27, "name": "H"}, {"age": 28, "name": "I"}, {"age": 29, "name": "J"}]
----+--------------------------------------------------------------------------------

5。选择+取消嵌套+分页+重新嵌套+自定义对象

我们可以接受之前的查询,并使用新字段重新构建新对象,例如person_idperson_info。这个 将返回带有新的自定义JSONB对象的单列(每id再次一行)。

with t_unnested as (
    select id, 
           jsonb_array_elements(data) as data
      from t 
     limit 5 offset 5
),
t_person as (
    select jsonb_build_object (
               'person_id', id,
               'person_info', jsonb_agg (data)
           ) as person
      from t_unnested
     group by id
)
select person from t_person;

-----------------------------------------------------------------------------------------------------------------
 person
-----------------------------------------------------------------------------------------------------------------
 {"person_id": 1, "person_info": [{"age": 25, "name": "F"}, {"age": 26, "name": "G"}]}
 {"person_id": 2, "person_info": [{"age": 27, "name": "H"}, {"age": 28, "name": "I"}, {"age": 29, "name": "J"}]}
-----------------------------------------------------------------------------------------------------------------

6。选择+取消嵌套+分页+重新嵌套+自定义对象+进一步重新嵌套

上一个查询返回了2行,我们可以再次使用jsonb_agg函数,即创建单行。

with t_unnested as (
    select id, 
           jsonb_array_elements(data) as data
      from t 
     limit 5 offset 5
),
t_person as (
    select jsonb_build_object (
               'person_id', id,
               'person_info', jsonb_agg (data)
           ) as person
      from t_unnested
     group by id
)
select jsonb_agg(person) from t_person;

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 person
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [{"person_id": 1, "person_info": [{"age": 25, "name": "F"}, {"age": 26, "name": "G"}]}, {"person_id": 2, "person_info": [{"age": 27, "name": "H"}, {"age": 28, "name": "I"}, {"age": 29, "name": "J"}]}]
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

希望这显示了JSONB / PostgreSQL在存储JSONB,取消分页(和重新分页)JSON数组中的功能。