有没有办法通过其值查找 jsonb 列

Is there a way to lookup a jsonb column by its values

我在 postgres 12 中有一个 table、test,带有一个 jsonb 列,data_col,它有许多不同的键和值。 我的要求是 select * 从那个 table 那里值匹配一个字符串。

例如table有如下数据

id   some_value  data_col
---------------------------------------------------------------       
11   2018        {"a": "Old Farm"}
12   2019        {"b": "My house is old", "c": "See you tomorrow"}
13   2020        {"d": "The old house", "a": "Very Green", "e": "Olden days"}

如您所见,有许多不同的键,因此像网络上的示例建议的那样查找是不切实际的,即 col_name->>'Key'

我想写一个带有 where 子句的 sql,以便为我提供其中包含字符串“old”的所有行。

类似于:

select * from test where data_col ILIKE '%old%'

应该给我

11, 2018, Old Farm
12, 2019, My house is old
13, 2020, Olden days

一个选项使用 jsonb_each():

select t.*, x.*
from test t
cross join lateral jsonb_each(t.data_col) x 
where x.value ilike '%old%'

请注意,如果一个对象不止一次包含“old”,这会增加行数。为避免这种情况,您可以使用 exists 代替:

select t.*
from test t
where exists (
    select 1
    from jsonb_each(t.data_col) x
    where x.val ilike '%old%'
)

或者,如果您想将所有匹配值汇总到一列中:

select t.*, x.*
from test t
cross join lateral (
    select string_agg(x.val, ',') as vals
    from jsonb_each(t.data_col) x
    where x.val ilike '%old%'
) x
where x.vals is not null

由于您使用的是 Postgres 12,因此您可以使用 SQL/JSON 路径函数:

select id, some_value, 
       jsonb_path_query_first(data_col, '$.* ? (@ like_regex "old" flag "i")') #>> '{}' 
from data

#>> 运算符仅用于将标量 JSON 值转换为文本(因为没有从 jsonbtext 的直接转换会删除双引号)

如果子字符串可能有更多值,您可以使用 jsonb_path_query_array() 将它们作为一个数组(显然您需要删除 #>> 然后)