簡體   English   中英

PostgreSQL 可以在 jsonb 數組對象上加入嗎?

[英]Can PostgreSQL JOIN on jsonb array objects?

由於 JSON 支持,我正在考慮切換到 PostgreSQL。 但是,我想知道,是否可以通過單個查詢實現以下功能:

假設有兩個表:

表 1) 組織:

  ID (INT)  |  members (JSONB)                                        |
------------+---------------------------------------------------------|
     1      | [{ id: 23, role: "admin" }, { id: 24, role: "default" }]|
     2      | [{ id: 23, role: "user" }]

表2)用戶:

  ID (INT)  | name TEXT | email TEXT    |
------------+-----------+---------------|
     23     | Max       | max@gmail.com |
     24     | Joe       | joe@gmail.com |

現在我想得到這樣的結果(我只有組織的 ID [1]):

  ID (INT)  |  members (JSONB)                                       |
------------+--------------------------------------------------------|
     1      | [{ id: 23, name: "Max", email: "max@gmail.com", role: 
                "admin" },
               { id: 24, name: "Joe", email: "joe@gmail.com ", role: 
                "default" }]
(1 row)

我知道這不是 JSONB 的目的,並且有一個更好的解決方案可以將這些數據存儲在 SQL 中,但我只是好奇是否有可能。

謝謝!

是的,使用 Postgres 可以滿足此要求。 這是 9.6 或更高版本的解決方案。

SELECT o.id,  
    JSON_AGG(
        JSON_BUILD_OBJECT('id', u.id, 'name', u.name, 'email', u.email, 'role', e.usr->'role')
    )
FROM organisations o
INNER JOIN LATERAL JSONB_ARRAY_ELEMENTS(o.data) AS e(usr) ON TRUE
INNER JOIN users u ON (e.usr->'id')::text::int = u.id
GROUP BY o.id

看到這個 db fiddle

解釋 :

  • JSONB_ARRAY_ELEMENTS函數將組織 json 數組拆分為行(每個用戶一個); 它通常與JOIN LATERAL結合使用

  • 為了加入users表,我們使用->操作符訪問id字段的內容

  • 對於每個用戶, JSONB_BUILD_OBJECT用於通過傳遞值/鍵對列表來創建新對象; 大多數值來自users表,除了role ,它取自組織 json 元素

  • 查詢按組織 id 聚合,使用JSONB_AGG通過組合上述對象生成 json 數組

有關更多信息,您還可以查看Postgres JSON 函數文檔

可能有更多方法可以做到這一點。 一種方法是使用jsonb_to_recordset()將 JSON 轉換為您可以加入的記錄集。 然后使用jsonb_build_object()為單個成員和jsonb_agg()從結果創建一個 JSON 以將它們聚合到 JSON 數組中。

SELECT jsonb_agg(jsonb_build_object('id', "u"."id",
                                    'name', "u"."name",
                                    'email', "u"."email",
                                    'role', "m"."role"))
       FROM "organisations" "o"
            CROSS JOIN LATERAL jsonb_to_recordset(o."members") "m" ("id" integer,
                                                                    "role" text)
            INNER JOIN "users" "u"
                       ON "u"."id" = "m"."id";

數據庫<>小提琴

具體可用哪些功能取決於版本。 但是既然你說你考慮切換,假設更新的版本應該是公平的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM