按值删除jsonb数组元素

时间:2016-10-27 13:15:25

标签: json postgresql jsonb

我确实弄清楚如何从单个记录的数组中删除一个值,但是如何为其中的许多记录删除它。问题在于我如何使用子查询。因为它必须只返回单个元素。也许我的做法是错误的。


    Given input: '{attributes:['is_new', 'is_old']}'
    Expected result '{attributes: ['is_old']}' #remove 'is_new' from jsonb array


    Real example:
    #   sku  |           properties 
    # -------+--------------------------------
    #  nu3_1 | {                             +
    #        |     "name": "silly_hodgkin",  +
    #        |     "type": "food",           +
    #        |     "attributes": [           +
    #        |         "is_gluten_free",     +
    #        |         "is_lactose_free",    +
    #        |         "is_new"              +
    #        |     ]                         +
    #        | }  


#Query that removes single array element:

SELECT c.sku, jsonb_agg(el) FROM
catalog c JOIN (select sku, jsonb_array_elements_text(properties->'attributes') as el from catalog) c2 ON c.sku=c2.sku where el  'is_new'
GROUP BY c.sku;

#Update query that removes single array element in single record

UPDATE catalog SET properties=jsonb_set(properties, '{attributes}', (
    SELECT jsonb_agg(el) FROM
    catalog c JOIN (select sku, jsonb_array_elements_text(properties->'attributes') as el from catalog) c2 ON c.sku=c2.sku
    WHERE el  'is_new' AND c.sku='nu3_1'
    GROUP BY c.sku
    )
) WHERE sku='nu3_1';

问题又来了。如何按许多数据库记录的值删除jsonb数组元素?

3 个答案:

答案 0 :(得分:11)

使用jsonb_set() and the delete operator -

update catalog
set properties = 
    jsonb_set(properties, '{attributes}', (properties->'attributes') - 'is_new');

Test it in rextester.

答案 1 :(得分:1)

所以,我相信你正在寻找的QRY是:

with q as (
  select distinct sku, jsonb_set(properties,'{attributes}',jsonb_agg(el) over (partition by sku),false) new_properties
  from (
    select 
      sku, jsonb_array_elements_text(properties->'attributes') as el, properties
    from catalog
  ) p
  where el != 'is_new'
)
update catalog set properties = q.new_properties from q where catalog.sku = q.sku
;

请注意,我认为您的sku至少是UK

答案 2 :(得分:0)

你的解决方案有效+你指出了一些像窗口功能这样的新东西,并给我一个替代解决方案的想法:

WITH q as (
  SELECT c.sku as sku,  jsonb_set(properties, '{attributes}', jsonb_agg(el)) as new_properties
    FROM catalog c JOIN (select sku, jsonb_array_elements_text(properties->'attributes') as el from catalog) c2 ON c.sku=c2.sku where el != 'is_new'
    GROUP BY c.sku
)
UPDATE catalog SET properties=q.new_properties FROM q WHERE catalog.sku=q.sku;