有什么方法可以使用匹配子句在json postgres列中进行搜索吗?

时间:2020-03-01 08:47:43

标签: sql json postgresql

我正在尝试从Postgres JSON列中搜索记录。存储的数据具有这样的结构

{
  "contract_shipment_date": "2015-06-25T19:00:00.000Z",
  "contract_product_grid": [
    {
      "product_name": "Axele",
      "quantity": 22.58
    },
    {
      "product_name": "Bell",
      "quantity": 52.58
    }
  ],
  "lc_status": "Awaited" 
}

我的表名是Heap,列名是contract_product_grid。另外,contract_product_grid列可以包含多个产品记录。 我找到了此文档,但无法获得所需的输出。

必要的情况是,我有一个筛选器,用户可以在其中选择product_name,并使用匹配子句在输入名称的基础上,将获取记录并返回给用户。

3 个答案:

答案 0 :(得分:0)

假设您输入了Axele作为product_name输入,并且想返回quantity键的匹配值。

然后使用:

SELECT js2->'quantity' AS quantity
  FROM
  (
   SELECT JSON_ARRAY_ELEMENTS(value::json) AS js2
     FROM heap,
     JSON_EACH_TEXT(contract_product_grid) AS js
    WHERE key = 'contract_product_grid' 
  ) q
  WHERE js2->> 'product_name' = 'Axele' 

其中,将最外面的JSON通过key扩展为valueJSON_EACH_TEXT(json)对,并通过JSON_ARRAY_ELEMENTS(value::json)函数将具有新形成的数组的所有元素拆分。

然后,在主查询中通过特殊的product_name进行过滤。

Demo

P.S。不要忘了用大括号将JSON列的值包装起来

答案 1 :(得分:0)

您需要取消嵌套数组才能在每个值上使用LIKE条件:

select h.*
from heap h
where exists (select * 
              from jsonb_array_elements(h.contract_product_grid -> 'contract_product_grid') as p(prod)
              where p.prod ->> 'product_name' like 'Axe%')

如果您真的不需要通配符搜索(因此用=而不是LIKE),则可以使用包含操作符@>,它效率更高:

select h.*
from heap h
where h.contract_product_grid -> 'contract_product_grid' @> '[{"product_name": "Axele"}]';

这也可以用于搜索多种产品:

select h.*
from heap h
where h.contract_product_grid -> 'contract_product_grid' @> '[{"product_name": "Axele"}, {"product_name": "Bell"}]';

如果您使用的是Postgres 12 ,则可以使用JSON path表达式来简化一下操作:

select *
from heap
where jsonb_path_exists(contract_product_grid, '$.contract_product_grid[*].product_name ? (@ starts with "Axe")')

或使用正则表达式:

select *
from heap
where jsonb_path_exists(contract_product_grid, '$.contract_product_grid[*].product_name ? (@ like_regex "axe.*" flag "i")')

答案 2 :(得分:0)

SELECT * FROM ( SELECT JSON_ARRAY_ELEMENTS(contract_product_grid::json) AS js2 FROM heaps WHERE 'contract_product_grid' = 'contract_product_grid' ) q WHERE js2->> 'product_name' IN ('Axele', 'Bell') 就像我提到的那样,我的列名是'contract_product_grid',我只需要从中搜索。 使用此查询,我可以使用带有输入产品名称的IN子句来获取contract_product_grid信息。

相关问题