How in PostgreSQL to update an attribute inside a column with a JSONB and also keeping the data already inside - postgresql

I have a situation where in a table called tokens I have a column called data
The data columns consist of something like this as a '{}'::jsonb
{"recipientId": "xxxxxxxx"}
My goal is to have as follow to update old data to new DB design and requirements
{"recipientIds": ["xxxxxxxx"]}
The reason is that the naming was changed and the value will be an array of recipients.
I don't know how to achieve this
change recipientIdto recipientIds
change the value format to an array but to not loose the data
Also this need to be done only where I have a type in ('INVITE_ECONSENT_SIGNATURE', 'INVITE_ECONSENT_RECIPIENT')
The table looks as follow is a simple table which contains few columns.
The data is the only one as '{}'::jsonb.
id
type
data
1
type1
data1
2
type2
data1
As an edit what I tried to do and partially solved my problem but cannot understand how to se the value to be [value]
update
"token"
set
"data" = data - 'recipientId' || jsonb_build_object('recipientIds', data->'recipientId')
where
"type" in ('INVITE_ECONSENT_RECIPIENT')
I can have now a recipientids: value but need to have recipientids: [value]

You were close, you need to pass an array as the second parameter of the jsonb_build_object() function:
(data - 'recipientId')||jsonb_build_object(
'recipientIds',
jsonb_build_array(data -> 'recipientId')
)

Related

Postgres Update Number Values in a JSONB field to be text

I have a table with a JSON column and some of the values in it are numbers but I want all the values to be text. For example, I have {"budget": 500}, but I want it to be {"budget":"500"}. I have tried using the JSONB_SET function but even after postgres returns N rows updated, when I go to retrieve the records, they are still numbers. I was hoping that somebody may have encountered this issue. Here's what I've tried that isn't working.
UPDATE my_table
SET data = JSONB_SET(data, '{budget}', data->'budget'::text)
WHERE data ? 'budget' = true;
Since this is a very large table, hardcoding values is not feasible. If anybody knows why this isn't working or if there is something that does work, please let me know, thank you!
You can enforce converting a JSONB number to text with the function quote_ident():
UPDATE my_table
SET data = jsonb_set(data, '{budget}', quote_ident(data->>'budget')::jsonb)
WHERE data ? 'budget'
-- you can add this condition to avoid updating non-numbers
-- AND jsonb_typeof(data->'budget') = 'number'
Note that data->'budget'::text does nothing as the cast refers to 'budget', not a JSON object and the expression is equivalent to data->'budget'.

Mapping Data Flows Dynamic Column Updates

I have a text input source. This has over 100 columns so I won't show all of them here - a cut-down view of the data would be:
CustomerNo
DOB
DOD
Status
01418495
01/02/1940
NULL
1
01418496
01/01/1930
NULL
1
The users want to be able to update/override any of these columns during processing by providing another input text file containing the PK (CustomerNo) and the key/value pairs of the columns to be updated e.g.
CustomerNo
Variable
New Value
01418495
DOB
01/12/1941
01418496
DOD
01/01/2021
01418496
Status
0
Can this data be used to create dynamic columns somehow that update the customer records regardless of the columns they want to update - in the example above this would result in:
CustomerNo
DOB
DOD
Status
01418495
01/02/1941
NULL
1
01418496
01/01/1930
01/01/2021
0
I have looked at the documentation but don't see any examples of how something like this could be achieved? Thanks in advance for any advice.
You would use a technique similar to what I describe in this video: https://www.youtube.com/watch?v=q7W6J-DUuJY. What I've done is created a file with rules that have expressions and then apply those rules dynamically inside of my data flow.
The key to make this work is using the expr() function to dynamically evaluate the expression from the external file.

Iterating a json array in postgresesql and filtering based on data

[{“name”=“abc”,”type”=“charts”},{“name”=“def”,”type”=“transactions”}]
Attachment column gives me this data but I need to iterate this and check if type is present and if type=charts or transactions ..mainly we need to filter it out .can someone help me on this as I am new to Postgres
It's unclear to me what exactly you want to filter.
If you just want to see rows that contain a specific type, you can use:
select *
from the_table
where attachment #> '[{"type": "transactions"}]';
This will return all rows that include at least one element with {"type": "transactions"} in the array.
This assumes that your attachment column is defined as jsonb. If it's not you will need to cast it.

How to SET jsonb_column = json_build_array( string_column ) in Sequelize UPDATE?

I'm converting a one-to-one relationship into a one-to-many relationship. The old relationship was just a foreign key on the parent record. The new relationship will be an array of foreign keys on the parent record.
(Using Postgres dialect, BTW.)
First I'll add a new JSONB column, which will hold an array of UUIDs.
Then I'll run a query to update all existing rows such that the value from the old column is now stored in the new column (as the first element in an array).
Finally, I'll remove the old column.
I'm looking for help with step 2: writing the update statement that will update all rows, setting the value of the new column based on the value of the old column. Basically, I'm trying to figure out how to express this SQL query using Sequelize:
UPDATE "myTable"
SET "newColumn" = json_build_array("oldColumn")
-- ^^ this really works, btw
Where:
newColumn is type JSONB, and should hold an array (of UUIDs)
oldColumn is type UUID
names are double-quoted because they're mixed case in the DB (shrug)
Expressed using Sequelize sugar, that might be something like:
const { models } = require('../sequelize')
await models.MyModel.update({ newColumn: [ 'oldColumn' ] })
...except that would result in saving an array that contains the string "oldColumn" rather than an array whose first element is the value in that row's oldColumn column.
My experience, and the Sequelize documentation, is focused on working with individual rows via the standard instance methods. I could do that here, but it'd be a lot better to have the database engine do the work internally instead of forcing it to transfer every row to Node and then back again.
Looking for whatever is the most Sequelize-idiomatic way of doing this, if there is one.
Any help is appreciated.

update table directly from json

I have some json as below
{"id":21,"name":"Ram","address":"mumbai","mobile":"1234567891"}
I have a table in postgres: tblstudents (id,name,address,mobile).
Now I want to update a record in this table directly from the input parameter as per the json above:
update tblstudents
set name=[name value from json],
address=[address value from json]
where id=[id value from json]
Actually this is a PUT request, and the parameter is sent as json from front end in postgres function. I want to update table using this json.
How can I achieve this functionality or what's the best way to achieve this?
You can use the jsonb_populate_record function to create the appropriate record. Postgres implicitly creates a type for your table, so you can use this:
UPDATE tblstudents
set name = json_record.name,
address = json_record.address
FROM jsonb_populate_record(null::tblstudents,
'{"id":21,"name":"Ram","address":"mumbai","mobile":"1234567891"}'::jsonb)
as json_record
WHERE json_record.id = tblstudents.id;