Prisma result processing into single object
I'm working on a nextjs 13 project with prisma ORM with MongoDB. Currently I am trying to fetch roles with permissions for admin role matrix. This is the Role model schema.
model Role {
id String @id @default(auto()) @map("_id") @db.ObjectId
name String @unique
userIDs String[] @db.ObjectId
users User[] @relation(fields: [userIDs], references: [id开发者_开发百科])
permissions String[]
@@map("roles")
}
When fetching the records I'd like to process them a little. Running this query returns such result.
const roles = await prisma.role.findMany({
select: {
name: true,
permissions: true,
}
})
console.log(roles);
[
{ name: 'User', permissions: [ 'permissions.user.view.dashboard' ] },
{
name: 'Admin',
permissions: [
'permissions.admin.view.dashboard',
'permissions.user.view.dashboard'
]
}
]
I need the results in one object with role name prepended to the permission like so
{
'User.permissions.user.view.dashboard',
'Admin.permissions.user.view.dashboard',
'Admin.permissions.admin.view.dashboard'
}
So my question is how would I do this? Preferably directly in prisma, but if it's not possible javascript will do.
You can use the map()
method to transform the roles
array into the desired object. The map()
method takes a callback function as its argument, which will be called for each element in the array. This callback function can be used to transform each element in the array into the desired format.
Here is an example of how you could use the map()
method to transform the roles array:
const roles = await prisma.role.findMany({
select: {
name: true,
permissions: true,
}
});
const processedRoles = roles.map((role) => {
const newPermissions = role.permissions.map((permission) => {
return `${role.name}.${permission}`;
});
return newPermissions;
});
console.log(processedRoles);
The map()
method will return a new array containing the transformed elements. In this case, the new array will contain the permission strings with the role name prepended to the permission.
You can then use the reduce()
method to combine the elements in the processedRoles
array into a single object. The reduce()
method takes a callback function as its argument, which will be called for each element in the array. This callback function can be used to combine the elements in the array into a single object.
Here is an example of how you could use the reduce()
method to combine the elements in the processedRoles
array into a single object:
const roles = await prisma.role.findMany({
select: {
name: true,
permissions: true,
}
});
const processedRoles = roles.map((role) => {
const newPermissions = role.permissions.map((permission) => {
return `${role.name}.${permission}`;
});
return newPermissions;
});
const result = processedRoles.reduce((acc, current) => {
return [...acc, ...current];
}, {});
console.log(result);
The reduce()
method will return a single object containing all of the elements in the processedRoles
array. This object will have the desired format, with the role name prepended to each permission.
You can also use the flat()
method to flatten the processedRoles array before passing it to the reduce()
method. This will avoid the need to use the spread operator (...) in the reduce()
method.
Here is an example of how you could use the flat()
and reduce()
methods together to transform the roles
array:
const roles = await prisma.role.findMany({
select: {
name: true,
permissions: true,
}
});
const processedRoles = roles.map((role) => {
const newPermissions = role.permissions.map((permission) => {
return `${role.name}.${permission}`;
});
return newPermissions;
});
const result = processedRoles.flat().reduce((acc, current) => {
return [...acc,
精彩评论