我有一个带有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是特定值的行,但是如何查询包含模式的行?
答案 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
和效果的说明。