Updating jsonb field using concatenation operator in postgres - postgresql

I am trying to update a jsonb field which has nested json objects in it using the concatenation operator in postgres as in dbfidde
But, it removes all other fields for example if I run the below script
UPDATE t
SET details = details || '{"name": {"firstname": "newname"},"address":{"city":"newCity"}}'
WHERE details -> 'name' ->>'firstname'='myname'
It removes the "lastname" field from the updated field
I tried updating with jsonb_set too but I am not sure how I can update multiple properties using jsonb_set

The || way does not work because the new name value is {"firstname":"newname"}. This replaces the complete old value {"firstname": "myname","lastname":"last"} and so removes the lastname attribute. This way only works if you are working on the toplevel fields. But you want to update the nested objects.
In that case I see no way around two separate calls of jsonb_set(). One possible way is to nest them:
demo:db<>fiddle
UPDATE t
SET details =
jsonb_set(
jsonb_set(details, '{name,firstname}','"newname"'),
'{address,city}',
'"newCity"'
)
WHERE details -> 'name' ->> 'firstname' = 'myname';
Updating the original details field; setting the new firstname value through the given path '{name,firstname}'
The resulting JSON object can be used directly for a following update of the city value using the same way.

Related

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

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')
)

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;

PostgreSql Search JSON And Match Whole Term

I have a Postgres database using JSON storage. I have a table of cameras and lenses with a single property to search against called BrandAndModel. The relevant JSON portion looks like this and is stored in a column called "data":
"BrandAndModel": "nikon nikkor 50mm f/1.4 ai-s"
I have a LIKE query running against this brand and model string but it only returns a result of the sequence of characters matches. For instance, the above does get results for "nikkor 50mm" but NOT "nikon 50mm".
I'm no SQL expert and I'm not sure what I need to use to match more possible combinations.
My query looks like this
SELECT * FROM listing where data ->> 'Product' ->> 'BrandAndModel' like '%nikon 50mm%'
How could I get this query to match "nikon 50mm"?
You may use ANY with an array for multiple comparisons.
LIKE ANY(ARRAY['%nikon%ai-s%', 'nikon%50mm%', '%nikkor%50mm%'])

SELECT query in PostgreSQL

I am trying to retrieve values from a PostgreSQL database in a variable using a WHERE clause, but I am getting an error.
The query is:
select age into x from employee where name=name.GetValue()
name is the textcontrol in which I am entering a value from wxpython GUI.
I am getting an error as name schema doesn't exist.
What is the correct method for retrieving values?
"name.GetValue()" is a literal string, you are sending that to your db which knows nothing about wxpython and nothing about the variables in your program. You need to send the value of that data to your db, probably using bound parameters. Something like:
cur.execute("select age from employee where name=%s", [name.GetValue()])
x = cur.fetchone()[0] # returns a row containing [age] from the db
is probably what you're after. This will create a query with a placeholder in the database, then bind the value of name.GetValue() to that placeholder and execute the query. The next line fetches the first row of the result of the query and assigns x to the first item in that row.
I'm not positive what you are trying to do, but I think your issue might be syntax (misuse of INTO instead of AS):
SELECT age AS x FROM employee WHERE name = ....