无论键如何,按值查询 postgres jsonb
Query postgres jsonb by value regardless of keys
我想获取 jsonb 字段中任何 value 包含文本的所有记录,而不考虑键。
例如:字段包含json{k1: 'hello', k2: 'world'}
。我想通过文本 'hello' 来获取这条记录。我不关心键或任何 json 结构,只关心值。
一个肮脏的 hack 是将字段转换为 varchar where jsonb_field::varchar like ...
,但这很丑陋,它也会匹配键和 {}。
另一个肮脏的黑客看起来像这样:
SELECT * FROM mytable AS m1 WHERE (
SELECT string_agg(value, '') FROM jsonb_each_text( (SELECT name FROM mytable AS m2 WHERE m1.id= m2.id)::jsonb )
) LIKE '%whatever%';
不过也很丑
我该怎么做?
对于简单的 JSON,您可以使用更合适的查询,例如
select *
from mytable t
where exists (
select 1
from jsonb_each_text(t.jsonbfield) j
where j.value = 'hello');
它适用于您示例中的 JSON,但对 {"a":"hello","b":1,"c":{"c":"world"}}
等更复杂的 JSON 没有帮助
我可以建议像这样创建存储函数
create or replace function jsonb_enum_values(in jsonb) returns setof varchar as $$
begin
case jsonb_typeof()
when 'object' then
return query select jsonb_enum_values(j.value) from jsonb_each() j;
when 'array' then
return query select jsonb_enum_values(a) from jsonb_array_elements() as a;
else
return next ::varchar;
end case;
end
$$ language plpgsql immutable;
列出所有值,包括递归对象(如何处理数组由您决定)。
这是用法示例:
with t(x) as (
values
('{"a":"hello","b":"world","c":1,"d":{"e":"win","f":"amp"}}'::jsonb),
('{"a":"foo","b":"world","c":2}'),
('{"a":[{"b":"win"},{"c":"amp"},"hello"]}'),
('[{"a":"win"}]'),
('["win","amp"]'))
select *
from t
where exists (
select *
from jsonb_enum_values(t.x) j(x)
where j.x = '"win"');
请注意,字符串值用双引号引起来。
我想获取 jsonb 字段中任何 value 包含文本的所有记录,而不考虑键。
例如:字段包含json{k1: 'hello', k2: 'world'}
。我想通过文本 'hello' 来获取这条记录。我不关心键或任何 json 结构,只关心值。
一个肮脏的 hack 是将字段转换为 varchar where jsonb_field::varchar like ...
,但这很丑陋,它也会匹配键和 {}。
另一个肮脏的黑客看起来像这样:
SELECT * FROM mytable AS m1 WHERE (
SELECT string_agg(value, '') FROM jsonb_each_text( (SELECT name FROM mytable AS m2 WHERE m1.id= m2.id)::jsonb )
) LIKE '%whatever%';
不过也很丑
我该怎么做?
对于简单的 JSON,您可以使用更合适的查询,例如
select *
from mytable t
where exists (
select 1
from jsonb_each_text(t.jsonbfield) j
where j.value = 'hello');
它适用于您示例中的 JSON,但对 {"a":"hello","b":1,"c":{"c":"world"}}
我可以建议像这样创建存储函数
create or replace function jsonb_enum_values(in jsonb) returns setof varchar as $$
begin
case jsonb_typeof()
when 'object' then
return query select jsonb_enum_values(j.value) from jsonb_each() j;
when 'array' then
return query select jsonb_enum_values(a) from jsonb_array_elements() as a;
else
return next ::varchar;
end case;
end
$$ language plpgsql immutable;
列出所有值,包括递归对象(如何处理数组由您决定)。
这是用法示例:
with t(x) as (
values
('{"a":"hello","b":"world","c":1,"d":{"e":"win","f":"amp"}}'::jsonb),
('{"a":"foo","b":"world","c":2}'),
('{"a":[{"b":"win"},{"c":"amp"},"hello"]}'),
('[{"a":"win"}]'),
('["win","amp"]'))
select *
from t
where exists (
select *
from jsonb_enum_values(t.x) j(x)
where j.x = '"win"');
请注意,字符串值用双引号引起来。