#Type reference and populate array

7 messages · Page 1 of 1 (latest)

long quail
#

Hi,

I've a schema that has a type:
@Prop({ type: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Role' }], }) @ValidateNested({ each: true }) roles: mongoose.Schema.Types.ObjectId[];
The Role schema has some fields and a "special" one, abilities:
@Prop({ type: Array<{ type: RoleAbility }>, default: [] }) @ValidateNested({ each: true }) abilities: [RoleAbility];
Where RoleAbility is an object with 2 strings.

Is there a way I can use populate('roles', 'abilities') and merge them?
Currently I get:
"roles": [ { "abilities": [ { "action": "manage", "module": "all" } ], }, { "abilities": [ { "action": "create", "module": "account" }, { "action": "create_sub", "module": "account" }, { "action": "update", "module": "account" }, ], } ]
and I'd like to get all elements concatenated and without the abilities key name:
"roles": [ { "action": "manage", "module": "all" }, { "action": "create", "module": "account" }, { "action": "create_sub", "module": "account" }, { "action": "update", "module": "account" } ]
Is this possible with ref or will I have to use a virtual or a post hook?

Ty

proud swan
#

If roles are only "actions" and "modules", then those should be the only props in Role. You don't need the sub-class "abilities". Or are there other props in the Role entity? It's very strange you are getting two abilities arrays. I'd almost venture to say, your document is messed up. Can you show us your Role entity code?

long quail
#

roles in the TeamSchema is an array of objectId that references Role.
Role has more properties (name, active,...), one of them being abilities that's also an array of RoleAbility (object: action, module).
Probably the best is to have a virtual:
TeamSchema.virtual('abilities'); TeamSchema.post('findOne', function (member) { // HOW DO I REFERENCE HERE ROLE COLLECTION TO FIND AND GET ITS ABILTIES?! for (const roleId of member.roles) { const role = ...findOne({ id: roleId }); abilities.concat(role.abilities); } });

proud swan
#

@long quail - Big bad code smell is a query inside a loop. Populate is the right thing to do to get roles and abilities. Why you are getting two ability keys is beyond me. It shouldn't happen. I'd worry more about the doubled up abilities key. Check the data in the database. Make sure it isn't also messed up (not sure that is even possible, but you never know).

long quail
#

I'm getting 2 abilities keys because roles is an array of role id and references role that has abilities' property.
Before populate:
"name": "System", "email": "[email protected]", "roles": [ "6364ef04ddd543f1fc87e01a", "6364ef04ddd543f1fc87e01c" ], "accountId": "1364ef04ddd543f1fc87e04a", "active": true,
After await data.populate('roles', 'abilities');:
"name": "System", "email": "[email protected]", "roles": [ { "abilities": [ { "action": "manage", "module": "all" } ], }, { "abilities": [ { "action": "create", "module": "account" }, { "action": "create_sub", "module": "account" }, { "action": "update", "module": "account" }, ], }, ],

proud swan
#

Ah, ok. But, aren't there more fields for each role (which is what confused me)? Where are the ids in the data? Are you using lean for the query by chance? In the end, if you need the data in another form, you'll need to change it yourself via code and at best, in your front-end. Also, if a certain role has certain abilities, why would you want them to be combined?

long quail
#

The Roles is a collection of their own, team members can be assign multiple roles.
I want to combine all abilities to get all the users' abilities in just one array, and not an array of arrays as I'm currently getting.
Probably going to create a specific route for the UI /users/me/abilities so it gives just the logged in user abilities and I can handle the data as necessary.
ty