Home > Software design >  Postgres JSON array - how to do select fields
Postgres JSON array - how to do select fields

Time:05-31

I have table in Postgres with JSONB filed. JSONB contains jsons as:

{
  "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
      }
    ]
  }
}

I need select following data-set (in SQL notation)

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

Plz help write query

CodePudding user response:

You can use a JSON path expression to filter out the needed rows:

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

To actually get the fullNumber you need to repeat the JSON path in order to extract the array element in question:

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)'

The WHERE condition can potentially make use of a GIN index on the_column to improve performance.

If there is no such index or performance isn't that important, you can avoid repeating the JSON path by using a derived table:

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

CodePudding user response:

You can use next query:

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 |
 -------------------------------------- ---------- ------------ 

CodePudding user response:

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;

since cast to text, somehow the first character of fullnumber is "

  • Related