0

in postgres 13, I have a Jsonb object and I am able to get only the keys using jsonb_object_keys like this.

SELECT keys from jsonb_object_keys('{
    "135": {
      "timestamp": 1659010504308,
      "priority": 5,
      "age": 20
    },
    "136": {
      "timestamp": 1659010504310,
      "priority": 2,
      "age": 20
    },
    "137": {
      "timestamp": 1659010504312,
      "priority": 2,
      "age": 20
    },
    "138": {
      "timestamp": 1659010504319,
      "priority": 1,
      "age": 20
    }}') as keys

Now, I want to get the keys which have priority more than 1 and which are ordered by priority and timestamp

I am able to achieve this using this query

select key from (
SELECT data->>'key' key, data->'value' value
FROM  
   jsonb_path_query(
   '{
  "135": {
    "name": "test1",
    "timestamp": 1659010504308,
    "priority": 5,
    "age": 20
    },
   "136": {
    "name": "test2",
    "timestamp": 1659010504310,
    "priority": 7,
    "age": 20
    },
   "137": {
    "name": "test3",
    "timestamp": 1659010504312,
    "priority": 5,
    "age": 20
    },
    "138": {
     "name": "test4",
     "timestamp": 1659010504319,
     "priority": 1,
     "age": 20
    }}'
   , '$.keyvalue() ? (@.value.priority > 1)')
    as data) as foo, jsonb_to_record(value) x("name" text, "timestamp" decimal,
                                                          "priority" int, 
                                                          "age" int)
    order by priority desc, timestamp desc

This doesn't seem to be the efficient way of doing this.

Please share if this can be achieved in a better way (by using jsonb_object_keys !??)

Thanks in advance.

Shrikar Kalagi
  • 91
  • 1
  • 11

1 Answers1

1

I would first 'normalize' JSON data into a table (the t CTE) and then do a trivial select.

with t (key, priority, ts) as
(
 select key, (value ->> 'priority')::integer, value ->> 'timestamp' 
 from jsonb_each('{
    "135": {"timestamp": 1659010504308,"priority": 5,"age": 20},
    "136": {"timestamp": 1659010504310,"priority": 2,"age": 20},
    "137": {"timestamp": 1659010504312,"priority": 2,"age": 20},
    "138": {"timestamp": 1659010504319,"priority": 1,"age": 20}
 }')
)
select key 
from t 
where priority > 1 
order by priority, ts;
Stefanov.sm
  • 11,215
  • 2
  • 21
  • 21
  • Great.. I am seeing almost 50% reduction in cost when I run `EXPLAIN (FORMAT JSON)` Can you please explain little more on how this is different from the one I shared? – Shrikar Kalagi Aug 03 '22 at 12:54
  • 1
    I am not sure that I can do this well enough, but generally `jsonb_each` seems to add less overhead then `jsonb_path_query` and no `jsonb_to_record` is needed. – Stefanov.sm Aug 03 '22 at 13:36