1
votes

Supprimer l'élément du tableau jsonb

J'ai le jsonb suivant. Des pages de tableau, je voudrais supprimer l'élément appelé «pageb». Les solutions proposées dans des questions similaires ne fonctionnent pas pour moi.

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

Mon script ressemble actuellement à ceci. Il ne renvoie aucune erreur mais les éléments ne seront pas supprimés.

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


2 commentaires

Double possible de Supprimer l'élément du tableau jsonb par valeur


La solution à cette question ne fonctionne tout simplement pas pour moi.


3 Réponses :


2
votes

Ce qui suit est une combinaison de la réponse fournie pour supprimer un élément à l'intérieur d'un tableau de manière fiable et la capacité de PostgreSQL à utiliser instructions de modification des données WITH , mais il a besoin d'une colonne d'identité ( id dans ma table test ) pour fonctionner en raison de corrélation nécessaire:

SELECT reports FROM test;
                                               reports                                               
-----------------------------------------------------------------------------------------------------
 {"data": {"id": "a1aldjfg3f", "pages": [{"type": "pagea"}, {"type": "pagec"}], "activity": "test"}}
 {"data": {"id": "a1aldjfg3f", "pages": [{"type": "pagea"}], "activity": "test"}}
 {"data": {"id": "a1aldjfg3f", "pages": [{"type": "pagec"}], "activity": "test"}}
(3 rows)

Les données de test que j'ai utilisées:

SELECT reports FROM test;
                                               reports                                               
-----------------------------------------------------------------------------------------------------
 {"data": {"id": "a1aldjfg3f", "pages": [{"type": "pagea"}, {"type": "pagec"}], "activity": "test"}}
 {"data": {"id": "a1aldjfg3f", "pages": [{"type": "pagea"}, {"type": "pageb"}], "activity": "test"}}
 {"data": {"id": "a1aldjfg3f", "pages": [{"type": "pageb"}, {"type": "pagec"}], "activity": "test"}}
(3 rows)

... et après avoir exécuté la requête:

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;

J'espère que cela fonctionne pour vous.


0 commentaires

3
votes

L'opérateur - ne peut pas être appliqué ici car l'opérande de droite est une chaîne définissant une clé, selon la documentation:

Supprimer la paire clé / valeur ou l'élément de chaîne de l'opérande gauche. Les paires clé / valeur sont mises en correspondance en fonction de leur valeur clé.

La suppression d'un objet json d'un tableau json peut être effectuée en décompressant le tableau et en trouvant l'index de l'objet. Une requête utilisant cette méthode peut être trop compliquée, donc définir une fonction personnalisée est très pratique dans ce cas.

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"}]';

Et la mise à jour:

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
$$;


0 commentaires

0
votes

Voilà

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
$$;


0 commentaires