Postgres JSON 数组 - 如何做 select 字段

Postgres JSON array - how to do select fields

我在 Postgres 中 table 归档了 JSONB。 JSONB 包含 jsons 为:

{
  "id": "adf59079-4921-4abc-a262-1dc8c2b1ccc7",
  "lastname": "LOBATOS",
  "firstname": "Leslie",
  "birth_date": "1988-01-26",
  "gender": 3,
  "contacts": {
    "phoneList": [
      {
        "fullNumber": "0671234567",
        "verifyStateId": 1
      },
      {
        "fullNumber": "0671234588",
        "verifyStateId": 0
      }
    ]
  }
}

我需要 select 以下数据集(以 SQL 表示法)

SELECT id, lastname, fullNumber FROM <JSONB-field> 
WHERE fullNumber LIKE '067%' and verifyStateId = 1

请帮忙写查询

您可以使用 JSON 路径表达式来筛选出所需的行:

where the_column @? '$.contacts.phoneList[*] ? (@.fullNumber like_regex "^067" && @.verifyStateId == 1)'

要实际获得 fullNumber,您需要重复 JSON 路径以提取相关数组元素:

select id, 
       the_column ->> 'lastname', 
       jsonb_path_query_first(the_column, 
                              '$.contacts.phoneList[*] ? (@.fullNumber like_regex "^067" && @.verifyStateId == 1)'
                             ) ->> 'fullNumber' as fullnumber
from the_table
where the_column @? '$.contacts.phoneList[*] ? (@.fullNumber like_regex "^067" && @.verifyStateId == 1)'

WHERE 条件可能会利用 the_column 上的 GIN 索引来提高性能。

如果没有这样的索引或性能不是那么重要,您可以通过使用派生的 table:

来避免重复 JSON 路径
select *
from (
  select id, 
         the_column ->> 'lastname', 
         jsonb_path_query_first(the_column, '$.contacts.phoneList[*] ? (@.fullNumber like_regex "^067" && @.verifyStateId == 1)') ->> 'fullNumber' as fullnumber
  from the_table
) t 
where fullnumber is not null

您可以使用下一个查询:

with unnested as (
  select 
    fld->>'id' id, fld->>'lastname' lastname, 
    jsonb_array_elements(((fld->>'contacts')::jsonb->>'phoneList')::jsonb)
from tbl
) select id, lastname, jsonb_array_elements->>'fullNumber' from unnested;

PostgreSQL fiddle

+======================================+==========+============+
| id                                   | lastname | ?column?   |
+======================================+==========+============+
| adf59079-4921-4abc-a262-1dc8c2b1ccc7 | LOBATOS  | 0671234567 |
+--------------------------------------+----------+------------+
| adf59079-4921-4abc-a262-1dc8c2b1ccc7 | LOBATOS  | 0671234588 |
+--------------------------------------+----------+------------+

demo


WITH cte AS (
    SELECT
        jsonb_path_query(data, '$.contacts.phoneList[*].verifyStateId')::text AS verifyStateId,
        jsonb_path_query(data, '$.id')::text AS id,
        jsonb_path_query(data, '$.lastname')::text AS lastname,
        jsonb_path_query(data, '$.contacts.phoneList[*].fullNumber')::text AS fullnumber
    FROM
        extract_jsonb
)
SELECT
    *
FROM
    cte
WHERE
    verifyStateId = '1'::text
    AND fullnumber ILIKE '"067%'::text;

由于转换为文本,不知为何 fullnumber 的第一个字符是 "