Reputation: 193
I have an angular app and the users can have multiple roles.
In the client when I remove or add a role to the user I send it to nodejs as an array of objects.
"roles": [
{
"role_id": 1,
"role_name": "Admin"
},
{
"role_id": 2,
"role_name": "Moderator"
}
],
my query :
for (i in roles) {
db.query(`
INSERT INTO user_roles (role_id, user_id)
VALUES($1, $2)
ON CONFLICT (role_id, user_id)
DO UPDATE
SET
role_id = $1,
user_id = $2`,
[roles[i].role_id, user_id], (err, data) => {
if (err) {
console.log(err)
} else {
console.log('inserted/deleted role')
}
})
}
Now, there are two issue:
1- when a user is created, they start with no roles and a null
array of objects is being passed roles: [ null ]
which will break the query because role.role_id is null.
2- If I want to remove a role, I am passing the below, but how do I add in the query that I want to remove the roles that don't exist in the array of objects?:
"roles": [
{
"role_id": 1,
"role_name": "Admin"
},
//the role moderator is removed from client so it's not being passed
],
Upvotes: 2
Views: 566
Reputation: 12494
I see you went with the many-to-many approach :-)
Just as PostgreSQL can make your query results into json for you, it can work with json you pass into the database. Again, I would ask the database to take care of this for you.
Instead of looping in your javascript, try something like this. It's a little verbose, but it should be easier to follow once you understand the individual parts.
db.query(`
WITH invars AS ( -- pass your parameter values only once
SELECT $2::INT as user_id, $1::JSONB as jdata
), newroles as ( -- expand to all valid role_id values, if none, then role_id will be null
SELECT user_id, (el->>'role_id')::INT as role_id
FROM invars
CROSS JOIN LATERAL JSONB_ARRAY_ELEMENTS(jdata) AS j(el)
), do_delete AS ( -- delete any existing user_roles that should not exist
DELETE FROM user_roles
USING invars
WHERE invars.user_id = user_roles.user_id
AND NOT EXISTS (SELECT 1
FROM newroles
WHERE role_id = user_roles.role_id)
) -- finally insert user_roles that do not exist
INSERT INTO user_roles (role_id, user_id)
SELECT role_id, user_id
FROM newroles n
WHERE role_id IS NOT NULL
AND NOT EXISTS (SELECT 1
FROM user_roles
WHERE (role_id, user_id) = (n.role_id, n.user_id))`,
[JSON.stringify(roles), user_id], (err, data) => {
if (err) {
console.log(err)
} else {
console.log('inserted/deleted role')
}
})
Upvotes: 1