在JSON数组中搜索包含与模式匹配的值的对象

时间:2018-04-13 20:12:14

标签: sql json postgresql pattern-matching

我有一个带有jsonb列的数据库,其中每行基本上包含一个名称值对数组。单个jsonb值的示例:

[
    {"name":"foo", "value":"bar"},
    {"name":"biz", "value":"baz"},
    {"name":"beep", "value":"boop"}
]

如何查询包含部分值的行?即,查找具有JSON对象键value ilike'%ba%'的行?

我知道我可以使用SELECT * FROM tbl WHERE jsoncol @> '[{"value":"bar"}]'查找JSON是特定值的行,但是如何查询包含模式的行?

2 个答案:

答案 0 :(得分:2)

没有内置的jsonb operators,也没有任何索引直接支持这种过滤器。

我建议EXISTS半连接:

SELECT t.*
FROM   tbl t
WHERE  EXISTS (
   SELECT FROM jsonb_array_elements(t.jsoncol) elem
   WHERE  elem->>'value' LIKE '%ba%'
   );

它避免了冗余评估以及使用普通DISTINCT获取不同行所需的最后CROSS JOIN步骤。

如果这还不够快,对于给定类型的查询,更复杂的专用解决方案的方法是每行提取一个连接的唯一值字符串(使用不会干扰搜索模式的分隔符)在IMMUTABLE函数中,在函数表达式上构建一个trigram GIN索引,并在查询中使用相同的表达式。

相关:

除此之外,如果您的jsonb值看起来真的像示例,那么您可以减少很多噪音并只存储:

[
   {"foo":"bar"},
   {"biz":"baz"},
   {"beep":"boop"}
]

答案 1 :(得分:1)

您可以在横向联接中使用函数jsonb_array_elements(),并在value子句中使用其结果WHERE

select distinct t.* 
from my_table t
cross join jsonb_array_elements(jsoncol)
where value->>'value' like '%ba%'

请阅读How to query jsonb arrays with IN operator,了解有关distinct和效果的说明。