在PostgreSQL中搜索嵌套的jsonb数组

Ste*_*lke 5 postgresql jsonb

我有一个订单表,我在jsonb列中存储订单摘要

 {"users": [
   {"food": [{"name": "dinner", "price": "100"}], "room": "2", "user": "bob"}, 
   {"room": "3", "user": "foo"}
 ]}
Run Code Online (Sandbox Code Playgroud)

现在我想users用他们的查询全部food->name.

我尝试了以下,但这也给了我用户foo,没有食物.

select 
  jsonb_array_elements(jsonb_array_elements(summary->'users')->'food')->>'name'  as food, 
  jsonb_array_elements(summary->'users')->>'user' as user_name 
from orders;

 food  | user_name 
 -------+-----------
 dinner | bob
 dinner | foo
Run Code Online (Sandbox Code Playgroud)

我该怎么做这样的查询?


UPDATE

我还有两个食物选择这样的夏季

{"users": [
  {"food": [{"name": "dinner", "price": "100"}, {"name": "breakfast", "price": "100"}], "room": "2", "user": "bob"}, 
  {"room": "3", "user": "foo"} 
]}
Run Code Online (Sandbox Code Playgroud)

而不是我得到:

   food    | user_name 
-----------+-----------
 dinner    | bob
 breakfast | foo
Run Code Online (Sandbox Code Playgroud)

理想情况下我想得到

   food               | user_name 
----------------------+-----------
 dinner, breakfast    | bob
Run Code Online (Sandbox Code Playgroud)

Bru*_*lza 6

好的,如果你这样做的话

SELECT jsonb_array_elements(summary->'users') as users FROM orders;
Run Code Online (Sandbox Code Playgroud)

你得到

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
?                                                      users                                                       ?
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
? {"food": [{"name": "dinner", "price": "100"}, {"name": "breakfast", "price": "50"}], "room": "2", "user": "bob"} ?
? {"room": "3", "user": "foo"}                                                                                     ?
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

让我们把这个选择放在另一个,选择我们需要的:

SELECT users->'user' as user_name, users->'food'->0->'name' as food FROM (
    SELECT jsonb_array_elements(summary->'users') as users FROM orders
) as s;

????????????????????????
? user_name ?   food   ?
????????????????????????
? "bob"     ? "dinner" ?
? "foo"     ? (null)   ?
????????????????????????
Run Code Online (Sandbox Code Playgroud)

我们很接近.我们只需要添加一个WHERE.

SELECT users->'user' as user_name, users->'food'->0->'name' as food FROM (
    SELECT jsonb_array_elements(summary->'users') as users FROM orders
) as s WHERE (users->'food') is not null;
Run Code Online (Sandbox Code Playgroud)

导致

????????????????????????
? user_name ?   food   ?
????????????????????????
? "bob"     ? "dinner" ?
????????????????????????
Run Code Online (Sandbox Code Playgroud)

如果食物阵列中有更多数据,例如

'{"users": [{"food": [{"name": "dinner", "price": "100"}, {"name" : "breakfast", "price" : "50"}], "room": "2", "user": "bob"}, {"room": "3", "user": "foo"}]}'
Run Code Online (Sandbox Code Playgroud)

你可以做

SELECT users->'user' as user_name, jsonb_array_elements(users->'food')->>'name' as food FROM (
    SELECT jsonb_array_elements(summary->'users') as users FROM orders
) as s WHERE (users->'food') is not null;
Run Code Online (Sandbox Code Playgroud)

?????????????????????????
? user_name ?   food    ?
?????????????????????????
? "bob"     ? dinner    ?
? "bob"     ? breakfast ?
?????????????????????????
Run Code Online (Sandbox Code Playgroud)

重写上述查询以使用公用表表达式

WITH users_data AS (
    SELECT jsonb_array_elements(summary->'users') as users FROM orders
), user_food AS (
    SELECT users->'user' as user_name, jsonb_array_elements(users->'food')->>'name' as food 
    FROM users_data
    WHERE (users->'food') is not null  
) SELECT * FROM user_food;
Run Code Online (Sandbox Code Playgroud)

现在我们只需要分组 user_name

WITH users_data AS (
    SELECT jsonb_array_elements(summary->'users') as users FROM orders
), user_food AS (
    SELECT users->'user' as user_name, jsonb_array_elements(users->'food')->>'name' as food 
    FROM users_data
    WHERE (users->'food') is not null  
) SELECT user_name, array_agg(food) foods FROM user_food GROUP BY user_name;
Run Code Online (Sandbox Code Playgroud)

最后结果

??????????????????????????????????
? user_name ?       foods        ?
??????????????????????????????????
? "bob"     ? {dinner,breakfast} ?
??????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

这是我能想到的最好的.如果你找到更好的方法,请告诉我.