2016-10-14 51 views
1

我正在使用postgres 9.5.4。Postgres:嵌套jsonb列的范围查询

从下面存储在jsonb列样品JSON数据,我想搜索记录匹配的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

非常感谢Klin。这对我有用。正如你所提到的,需要检查大数据集上的性能。 – Carbonrock

+0

@ klin,在citus集群上执行此查询时遇到问题。需要帮忙。 (1)从jsontest,jsonb_array_elements(data - >'o')where(value - >>'mid'):: int> 7000; 错误:无法对此查询执行分布式计划 详细信息:目前不支持复杂表表达式 – Carbonrock

+0

不幸的是,这不是标准的Postgres错误消息。似乎citus有其他限制,请参阅[this citus问题](https://github.com/citusdata/citus/issues/521)。 – klin