简体   繁体   中英

postgres jsonb, query an array of objects

i've a jsonb field containing json from iiif manifests.
i'm interested in extracting the metadata block, is an array of json objects in the form

{label:"', value:""}

example:

"metadata": [
    {
        "label": "Homepage",
        "value": "<span><a href=\"https://digital.bodleian.ox.ac.uk/inquire/p/1bac4a1e-fba6-4466-baf5-ef2d45a47ec1\">View on Digital Bodleian</a></span>"
    },
    {
        "label": "Creator",
        "value": "Exeter-'Change (London, England) [author]"
    },
    {
        "label": "Contributors",
        "value": "Incledon, Charles Benjamin, 1763-1826 [performer]"
    },
    {
        "label": "Date Statement",
        "value": "1781-11-24"
    }
]

i would like a query to have columns named as label with the relative value , for all objects of metadata[] , as example:

|Creator                                    |Contributors                                     |
|-------------------------------------------|-------------------------------------------------|
|Exeter-'Change (London, England) [author]  |Incledon, Charles Benjamin, 1763-1826 [performer]|

is this a trivial query to compose?

It can be trivial [or not].

If you know every label from metadata (perhaps because you extracted them earlier) then you can use the pivot table function of postgresql:

First you need to enable the function:

CREATE extension tablefunc;

then you can use crosstab like that:

SELECT * FROM crosstab ('
    SELECT t.id as id, m->>''label'', m->>''value'' 
        FROM import.manifest t, 
             LATERAL jsonb_array_elements(t.data->''metadata'') m 
        ORDER BY 1,2
    ', '
        select distinct m->>''label'' 
            FROM import.manifest t, 
                 LATERAL jsonb_array_elements(t.data->''metadata'') m 
            order by 1
    ') AS ct (id int,Author text, Contributors text, Creator text, "Date Statement" text, Homepage text, Published text);

You have to put all your label in the query it is why it is not so trivial.

The crosstab function take 2 parameters:

  • first one is the SQL that return 3 column:
    • One ID column to join data
    • key column. Text from this column will be the name of a column in the result
    • value column
  • Second one, is a SQL that return all columns you will have.

With the function, you also need to define the result you will have. It means the as ct(....) is mandatory. it must reference the id column and all the column you will have for return. for your use case, it is the return of:

select distinct(m->>'label') 
    FROM manifest t, LATERAL jsonb_array_elements(t.data->'metadata') m 
    order by 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM