postgresql - 无论键如何,按值查询 postgres jsonb

标签 postgresql postgresql-9.4 jsonb

我想获取所有记录,其中 jsonb 字段中的任何 都包含一个文本,而不考虑键。

例如:字段包含json {k1: 'hello', k2: 'world'}。我想通过文本“你好”获得这条记录。我不关心键或任何 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,但对更复杂的 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($1)
    when 'object' then
      return query select jsonb_enum_values(j.value) from jsonb_each($1) j;
    when 'array' then
      return query select jsonb_enum_values(a) from jsonb_array_elements($1) as a;
    else
      return next $1::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"');

请注意字符串值周围的双引号。

关于postgresql - 无论键如何,按值查询 postgres jsonb,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36250331/

相关文章:

json - jsonb 字段中的 PostgreSQL 重命名属性

postgresql - postgres 函数和事务与 BEGIN

sql - 具有 generate_series 性能问题的 PostgreSQL CTE/子查询

sql - Postgresql 和 jsonb - 将键/值插入多级数组

arrays - 将 HSTORE 数组值转换为 JSONB 中的列

sql - 具有相同外键唯一约束的Postgresql多个表

python - 由于python中的双反斜杠导致的sql语法错误

postgresql - psql 提示符中的颜色

mysql - chown : changing ownership of '' ": Input/output error

postgresql - 如何用两个单引号字符替换一个单引号字符