从jsonb数组中删除元素

时间:2019-03-05 10:02:58

标签: postgresql jsonb

我有以下jsonb。我想从数组页面中删除名为“ pageb”的元素。类似问题中提供的解决方案对我不起作用。

'{
  "data": {
    "id": "a1aldjfg3f",
    "pages": [
      {
        "type": "pagea"
      },
      {
        "type": "pageb"
      }                                
    ],
    "activity": "test"
  }
}'

我的脚本现在看起来像这样。它不会返回任何错误,但不会删除元素。

  UPDATE database
  SET reports = jsonb_set(reports, '{data,pages}', (reports->'data'->'pages') - ('{"type":"pageb"}'), true)
  WHERE reports->'data'->'pages'  @> '[{"type":"pageb"}]';

3 个答案:

答案 0 :(得分:1)

此处不能应用-运算符,因为右侧操作数是定义键per the documentation:的字符串

  

从左操作数中删除键/值对或字符串元素。键/值对基于其键值进行匹配。

可以从json数组中删除json对象,方法是将数组拆包并找到对象的索引。使用这种方法的查询可能太复杂了,因此在这种情况下定义自定义函数非常方便。

create or replace function jsonb_remove_array_element(arr jsonb, element jsonb)
returns jsonb language sql immutable as $$
    select arr- (
        select ordinality- 1
        from jsonb_array_elements(arr) with ordinality
        where value = element)::int
$$;

更新:

update my_table
set reports = 
    jsonb_set(
        reports, 
        '{data,pages}', 
        jsonb_remove_array_element(reports->'data'->'pages', '{"type":"pageb"}')
        )
where reports->'data'->'pages'  @> '[{"type":"pageb"}]';

Working example in rextester.

答案 1 :(得分:0)

以下是answer provided(用于可靠地删除数组中的元素)与PostgreSQL使用data-modifying WITH statements的能力的组合,但是它需要在我的{ {1}}表)由于必要的相关性而可以正常工作:

id

我使用的测试数据:

test

...并执行查询后:

WITH new_reports AS (
    SELECT
        id,
        reports #- array['data','pages',(position - 1)::text] AS new_value
    FROM
        test,
        jsonb_array_elements(reports->'data'->'pages') WITH ORDINALITY arr(item, position)
    WHERE
        test.reports->'data'->'pages' @> '[{"type":"pageb"}]'
        AND
        item->>'type' = 'pageb'
    )
UPDATE test SET reports = new_reports.new_value FROM new_reports WHERE test.id = new_reports.id;

我希望对您有用。

答案 2 :(得分:0)

你去了

do $$
declare newvar jsonb;
begin
    newvar := jsonb '{ "customer": "John Doe", "buy": [{"product": "Beer","qty": 6},{"product": "coca","qty": 5}]}';
    newvar := jsonb_set(newvar,'{buy}', jsonb_remove((newvar->>'buy')::jsonb,'{"product": "Beer"}'));
    newvar := jsonb_set(newvar,'{buy}', jsonb_add((newvar->>'buy')::jsonb,'{"product": "cofe","qty": 6}'));
    RAISE NOTICE '%', newvar; 
end $$

create or replace function jsonb_remove(arr jsonb, element jsonb)
returns jsonb language sql immutable as $$
    select ('['||coalesce(string_agg(r::text,','),'')||']')::jsonb from jsonb_array_elements(arr) r where r @> element=false
$$;

create or replace function jsonb_add(arr jsonb, element jsonb)
returns jsonb language sql immutable as $$
    select arr||element
$$;