Reputation: 87
folks! I have table Template with only 1 column from type JSON. column
{
"name": "any name",
"headers": {
"Accept": ["application/json"],
"ApiSecret": ["keySecret==="],
"ApiSecretKey": ["key==="],
"X-Auth-Token": ["token=="],
"OAUTH-Token": ["token2=="],
"Authorization": ["basicAuth"]
},
"description": "any desc"
}
I have to remove all headers like %authorization%, %token%, %apiSecret%.
I created the following query:
UPDATE template as w
SET
column = column::jsonb - ARRAY(select wf.elements
from (select jsonb_object_keys(column->'headers') as elements
from template) as wf
where LOWER(wf.elements) LIKE ANY(ARRAY['%authorization%','%token%','%apikey%']));
Unfortunately my query does not work. Where could be the problem?
Upvotes: 0
Views: 337
Reputation: 7065
(a) You cant't mix jsonb type with array type : column::jsonb - ARRAY(...)
is not allowed.
(b) If you want to remove several key/value pairs from the same jsonb data, then you have to create a user-defined aggregate
based on the jsonb #-
operator :
CREATE OR REPLACE FUNCTION jsonb_remove(x jsonb, y jsonb, p text[])
RETURNS jsonb LANGUAGE sql IMMUTABLE AS
$$ SELECT COALESCE(x, y) #- p ; $$ ;
DROP AGGREGATE IF EXISTS jsonb_remove_agg(jsonb, text[]) ;
CREATE AGGREGATE jsonb_remove_agg(jsonb, text[])
( sfunc = jsonb_remove
, stype = jsonb
) ;
Then you can iterate on the new aggregate within a query :
UPDATE template as w
SET
column = l.elements
FROM
( SELECT id -- id is to be replaced by the primary key of table template
, jsonb_remove_agg(column, array['headers', wf.elements]) as elements
FROM template
CROSS JOIN LATERAL jsonb_object_keys(column->'headers') as wf(elements)
WHERE LOWER(wf.elements) LIKE ANY(ARRAY['%authorization%','%token%','%apikey%'])
GROUP BY id -- id is to be replaced by the primary key of table template
) AS l
WHERE w.id = l.id ; -- -- id is to be replaced by the primary key of table template
see the test result in dbfiddle.
Upvotes: 1