2016-10-14 2 views
1

Я использую postgres 9.5.4.Postgres: Запрос диапазона на вложенной колонке jsonb

Снизу данных JSon образцов, хранящихся в колонке jsonb, я хотел бы искать записи соответствия o['mid'] > 7000

Это пример записи одного пользователя. Будут миллионы таких пользователей.

{ 
    "uid": 14105529, 
    "o": [ 
    { 
     "mid": 6551, 
     "ac": 1913, 
     "ip": "144.36.233.44", 
     "adw": 5, 
     "at": 133000, 
     "ad": 151015, 
     "aid": 0 
    }, 
    { 
     "mid": 7552, 
     "ac": 1913, 
     "ip": "144.36.233.44", 
     "adw": 5, 
     "at": 133000, 
     "ad": 151015, 
     "aid": 0 
    }, 
    { 
     "mid": 7553, 
     "ac": 1913, 
     "ip": "144.36.233.44", 
     "adw": 5, 
     "at": 133000, 
     "ad": 151015, 
     "aid": 0 
    } 
    ] 
} 

ответ

2
with a_table(jdata) as ( 
values (
    '{ 
     "uid":14105529, 
     "o":[ 
      {"mid":6551,"ac":1913,"ip":"144.36.233.44","adw":5,"at":133000,"ad":151015,"aid":0}, 
      {"mid":7552,"ac":1913,"ip":"144.36.233.44","adw":5,"at":133000,"ad":151015,"aid":0}, 
      {"mid":7553,"ac":1913,"ip":"144.36.233.44","adw":5,"at":133000,"ad":151015,"aid":0} 
     ] }'::jsonb 
    ) 
) 

select jdata->'uid' as uid, value 
from a_table, jsonb_array_elements(jdata->'o') 
where (value->>'mid')::int > 7000; 

    uid |            value            
----------+-------------------------------------------------------------------------------------------------- 
14105529 | {"ac": 1913, "ad": 151015, "at": 133000, "ip": "144.36.233.44", "adw": 5, "aid": 0, "mid": 7552} 
14105529 | {"ac": 1913, "ad": 151015, "at": 133000, "ip": "144.36.233.44", "adw": 5, "aid": 0, "mid": 7553} 
(2 rows) 

Запрос будет очень дорогим для большого набора данных из-за необходимости unnesting массива JSon с jsonb_array_elements(). Нет индекса, который вы могли бы использовать для его ускорения.

+0

Большое спасибо Клин. Это работает для меня. Как вы упомянули, необходимо проверить производительность на большом наборе данных. – Carbonrock

+0

@ klin, сталкиваясь с проблемой при выполнении этого запроса в кластере citus. Нужна помощь. postgres = # select count (1) from jsontest, jsonb_array_elements (data -> 'o') где (значение - >> 'mid') :: int> 7000; ОШИБКА: не удается выполнить распределенное планирование по этому запросу ДЕТАЛИ: Сложные выражения таблиц в настоящее время не поддерживаются – Carbonrock

+0

К сожалению, это не стандартное сообщение об ошибке Postgres. Кажется, у citus есть дополнительные ограничения, см. [This citus issue] (https://github.com/citusdata/citus/issues/521). – klin

Смежные вопросы