如果对象不退出,则将concat对象转换为数组

时间:2017-04-12 21:06:35

标签: arrays postgresql jsonb

mycolumn是一个jsonb类型,默认值为空数组。

如果新值尚未存在,我想更新此数组。

选择查询:

SELECT mycolumn FROM mytable WHERE id = 1;

返回:[]

更新查询:

UPDATE mytable SET mycolumn = mycolumn || '[{"foo":"bar"}]' WHERE id = 1;

选择退货:[{"foo":"bar"}]

如果更新查询多次运行,它会将值附加到数组。

再次运行更新,选择返回[{"foo":"bar"},{"foo":"bar"}]

是否存在更新mycolumn数组值的幂等方法?

3 个答案:

答案 0 :(得分:1)

使用<@@>运算符检查数组中是否已存在值:

UPDATE mytable
SET mycolumn = mycolumn || '[{"foo":"bar"}]'
WHERE id = 1 AND NOT '[{"foo":"bar"}]'::jsonb <@ mycolumn;

请注意,它仅适用于单个值。例如:

select '[{"foo":"bar"},{"foo":"baz"}]'::jsonb <@ '[{"foo":"bar"},{"win":"amp"}]'::jsonb;
即使它有共同的{"foo":"bar"}对象,

也是假的。在这种情况下,你应该分解数组并使用DISTINCT:

再次组合它
UPDATE mytable
SET mycolumn = (
  SELECT jsonb_agg(DISTINCT j) 
  FROM jsonb_array_elements(mycolumn || '[{"foo":"bar"},{"win":"amp"}]') AS j);

答案 1 :(得分:1)

如果&#34;部分&#34;遏制不在桌面上,然后遏制操作符(<@@>)对你没有好处。您需要检查每个元素是否相等:

with append(a) as (
  values (jsonb '{"foo":"bar"}')
)
update mytable
set    mycolumn = mycolumn || a
from   append
where  id = 1
and    not exists(
  select 1
  from   jsonb_array_elements(mycolumn) e
  where  e = a
)

注意:如果你愿意重复你想要的JSON对象,你可以避免使用CTE(WITH子句。&#34;插入&#34;。

http://rextester.com/IAHE54266

答案 2 :(得分:0)

我认为您选择了错误的jsonb数据结构。听起来你使用了一个对象数组,而你应该使用一个对象,就像一个字典。

试试这个:

create table mytable (id serial primary key, mycolumn jsonb not null default '{}');
insert into mytable values (default);
update mytable set mycolumn = mycolumn || '{"foo":"bar"}'::jsonb;
update mytable set mycolumn = mycolumn || '{"foo":"baz"}'::jsonb;
update mytable set mycolumn = mycolumn || '{"stack":"overflow"}'::jsonb;
select * from mytable;
 id |              mycolumn               
----+-------------------------------------
  1 | {"foo": "baz", "stack": "overflow"}