Home > database >  how to query postgres jsonb for following json and make it available as part of the result
how to query postgres jsonb for following json and make it available as part of the result

Time:06-30

I have the following record as a jsonb field in a PG13 table

meta 
{"subscriptions": [{"location_id": 14555, "practice_area_id": 39, "monthly_quota_views": 300, "remaining_views": 300}, 
                   {"location_id": 14832, "practice_area_id": 39, "monthly_quota_views": 250, "remaining_views": 250}, 
                   {"location_id": 17793, "practice_area_id": 39, "monthly_quota_views": 700, "remaining_views": 700}]}

I'd like to query for location_id: 14555, practice_area_id: 39 and having remaining_views > 0. Also, I'd like to return the selected hash from the array as part of the result (if possible).

I have

SELECT * FROM mytable WHERE 
meta->'subscriptions' @> '[{"location_id":14555}]' and 
meta->'subscriptions' @> '[{"practice_area_id":39}]';

but how would I check for remaining_views > 0 and return that selected hash as part of the result? Is there a less bulky way of writing this query? Thanks

CodePudding user response:

You can use a JSON path expression to filter the desired elements and also return only those:

select jsonb_path_query_array(meta, '$.subscriptions[*] ? (@.location_id == 14555 && @.practice_area_id == 39 && @.remaining_views > 0)')
from the_table
where meta @? '$.subscriptions[*] ? (@.location_id == 14555 && @.practice_area_id == 39 && @.remaining_views > 0)';

Based on your sample data, the above returns:

jsonb_path_query_array                                                                              
----------------------------------------------------------------------------------------------------
[{"location_id": 14555, "remaining_views": 300, "practice_area_id": 39, "monthly_quota_views": 300}]

If you are certain there will be only one element matching your condition, you can use jsonb_path_query_first() instead

CodePudding user response:

I suspect by "return the selected hash from the array" you refer to the object that is contained in the subscriptions array.

There are two ways to do this:

  • use jsonb_array_elements to get the individual objects:

    SELECT *
    FROM pg13,
    LATERAL jsonb_array_elements(pg13.meta -> 'subscriptions') el
    WHERE el->>'location_id' = '14555'
      AND el->>'practice_area_id' = '39'
      AND (el->>'remaining_views')::int > 0
    
  • use a json path query:

    SELECT *, jsonb_path_query(meta, '$.subscriptions[*] ? (@.location_id == 14555 && @.practice_area_id == 39 && @.remaining_views > 0)')
    FROM pg13
    
  • Related