Postgres:创建一个匹配值的新jsonb对象

时间:2018-01-25 14:21:05

标签: postgresql

所以我的这个表questions有一个settings jsonb列:

{
    id: 'question-id-1',
    settings: {
      foo1: true,
      foo2: true,
      bar: false
    }
},
{
    id: 'question-id-2',
    settings: {
      bar: true
    }
}

现在我想创建一个postgres db update migration脚本,结果是:

{
    id: 'question-id-1',
    settings: {
      foo1: true,
      foo2: true,
      bar: false,
      opts: ['foo1', 'foo2']
    }
},
{
    id: 'question-id-2',
    settings: {
      bar: true,
      opts: ['bar']
    }
}

因此,只有值为true的广告会添加到opts内的新settings数组中。

这适用于Postgres 9.5。

先谢谢你。

1 个答案:

答案 0 :(得分:0)

创建一个更新列的函数:

create or replace function add_opts(jsonb)
returns jsonb language sql as $$
    select $1 || jsonb_build_object('opts', jsonb_agg(key))
    from jsonb_each_text($1)
    where value::bool;
$$;

测试:

with questions(settings) as (
values
('{
  "foo1": true,
  "foo2": true,
  "bar": false
}'::jsonb)
)

select add_opts(settings)
from questions;

                               add_opts                               
----------------------------------------------------------------------
 {"bar": false, "foo1": true, "foo2": true, "opts": ["foo1", "foo2"]}
(1 row)

您的更新查询应如下所示:

update questions
set settings = add_opts(settings);

在没有设置选项时消除opts数组的变体:

create or replace function add_opts(jsonb)
returns jsonb language sql as $$
    select case
        when jsonb_agg(key) is null then $1
        else $1 || jsonb_build_object('opts', jsonb_agg(key))
    end
    from jsonb_each_text($1)
    where value::bool;
$$;