从Postgres中的jsonb中选择匹配元素

时间:2017-03-03 21:37:50

标签: postgresql jsonb

我有订单表,其中包含一个名为商店的列,其中jsonb包含许多元素,例如

 id  status        stores
  1  in progress   [{"id": 1, "lat": 19.41, "lng": -99.18, "name": "Domino´s pizza condesa", "products": "3 tacos de cabeza"},
                    {"id": 2, "lat": 19.03, "lng": -99.9, "name": "Papa guapa roma", "products": "una papa"}]

  1  done          [{"id": 3, "lat": 19.44, "lng": -99.28, "name": "ABC", "products": "3 tacos de cabeza"},
                    {"id": 4, "lat": 19.23, "lng": -99.29, "name": "Papa guapa roma", "products": "una papa"}]

我想查询表顺序,只选择json中匹配{"lat:19.41", "lng":-99.18}的元素

所以我得到像

这样的东西
id  status        store_filtered
 1  in progress   [{"id": 1, "lat": 19.41, "lng": -99.18, "name": "Domino´s pizza condesa", "products": "3 tacos de cabeza"}]

我目前有

SELECT id, status, stores->0 AS stores_filtered FROM orders WHERE stores @> '[{"lat":19.41, "lng": -99.18}]'

但是那个0是我需要动态的,给我一个与第一个不匹配的元素。

2 个答案:

答案 0 :(得分:0)

假设您正在使用PostgreSQL 9.5(或更新版本),您可以使用jsonb_array_elements(json)(或jsonb_array_elements(json))函数来解决问题"不需要"数组,然后选择。

例如,您可以尝试:

WITH orders(id, status, stores) AS
(
VALUES
    (1,  'in progress',
        '[{"id": 1, "lat": 19.41, "lng": -99.18, "name": "Domino´s pizza condesa", "products": "3 tacos de cabeza"},
         {"id": 2, "lat": 19.03, "lng": -99.9, "name": "Papa guapa roma", "products": "una papa"}]'::jsonb),

    (1,  'done', 
         '[{"id": 3, "lat": 19.44, "lng": -99.28, "name": "ABC", "products": "3 tacos de cabeza"},
           {"id": 4, "lat": 19.23, "lng": -99.29, "name": "Papa guapa roma", "products": "una papa"}]')
)
, expanded_stores AS
(
SELECT
    id, status, jsonb_array_elements(stores) AS single_store
FROM
    orders
)
SELECT
    id, status, single_store AS filtered_store
FROM
    expanded_stores
WHERE 
    single_store @> '{"lat":19.41, "lng": -99.18}'

或者,假设您已经声明了orders表,您可以使用:

SELECT
    id, status, single_store AS filtered_store
FROM
    (
    SELECT
        id, status, jsonb_array_elements(stores) AS single_store
    FROM
        orders
    ) AS expanded_stores
WHERE 
    single_store @> '{"lat":19.41, "lng": -99.18}' ;

您可以在http://rextester.com/MQE36487检查版本9.5。

注意:虽然这确实有效但看起来有点不自然"对于SQL数据库。通常更容易规范化信息,并在真正需要大量模式灵活性的地方保留JSON。

答案 1 :(得分:0)

以r为( 选择状态,不选择(存储)作为商店 来自订单 ) select * from r where stores-> lat =' 19.41'和商店 - > lng =' -99.18'