将 JSONB 列连接到 Postgres 中的普通 PK 列

CSh*_*Atl 1 postgresql join json postgresql-9.6

我正在尝试通过 Postgres 中 jsonb 字段上的属性将普通表连接到具有 jsonb 字段的表。例子:

普通表:

create table Res
(
    id uuid default uuid_generate_v4() not null
        constraint res_pkey
            primary key
)
;
Run Code Online (Sandbox Code Playgroud)

带有 jsonb 的表:

create table res_rem_sent
(
    body jsonb not null,
    search tsvector,
    created_at timestamp with time zone default now(),
    id uuid default uuid_generate_v4() not null
        constraint res_rem_sent_pkey
            primary key
);

create index idx_res_rem_sent
    on res_rem_sent (body)
;

create index idx_search_res_rem_sent
    on res_rem_sent (search)
;
Run Code Online (Sandbox Code Playgroud)

body字段可能如下所示:{"resId": <GUID>, ....}

我想将res表连接到id等于给定 GUID id 的res_rem_sent表。resIdres

joa*_*olo 5

您可以使用以下查询:

SELECT
    *
FROM
    res
    JOIN res_rem_sent ON res_rem_sent.body->>'resId' = text(res.id) ;
Run Code Online (Sandbox Code Playgroud)

JSON 将其所有内容表示为文本,这就是您必须非常小心 PostgreSQL 如何将 UUID 转换为文本的原因。

需要考虑的事项:

  1. ->>运算符获取一个 JSON 对象字段作为 text

  2. 在 JSON(B) 方面,您需要使用标准形式表示 UUID (如UUID 类型中所述),以便 UUID 类型到 JSON(B) 文本表示形式之间的转换产生相同的结果。

  3. 如果您希望查询具有高性能,则至少需要在该body->>'resId'部分上有一个(功能)索引

    CREATE INDEX idx_uuid_res_rem_sent ON res_rem_sent((body->>'resId')) ;
    -- NOTE: the double parenthesis aren't optional

  4. 如果您还有一个文本索引,您将获得最大性能Res.id

    CREATE INDEX idx_uuid_res ON Res(text(id)) ;

  5. 如果不使用文本表示,而是使用 UUID 表示来完成比较和索引,则可能会提高性能:

    (res_rem_sent.body->>'resId')::uuid = res.id
    在这种情况下,如果转换失败,您将无法将数据插入到表中。

DBfiddle 这里可以看到这个场景的实际模拟