0

So I have this function to return User B data based on the access privileges of User A:

get: (userToGet, userWithAccess, done) => {
        userModel
            .aggregate([
                { $match: { name: userToGet } }, // Match user
                { $unwind: '$decks' },           // Split decks to check seperatly
                {
                    $match: {
                        $or: [
                            { 'decks.users': userWithAccess.name },  // Check if user access
                            { 'decks.groups': { $in: userWithAccess.groups } } // Check if shared group access
                        ]
                    }
                },
                { $group: {
                    '_id': {
                        'name': '$name'
                    },
                    'decks': { $push: '$decks.name' }
                }}
            ])
            .exec((err, data) => { // Run
                done(err, data);   // Return data
            });
    }

This works as intended, if the user has access to a deck the deck is returned and the ones he does not have access to is removed from the returning data. However, if a user has no access to any of the decks the returned data is {}.

I want to return the base information beyond just the deck. So if the user has no deck access return:

{
  _id: {
    'name: 'User B'
  },
  'decks': [] // empty array or no 'decks' property at all works
}

Why $filter $project is not working:

{ $match: { $or: [
                    { 'decks.users': userWithAccess.name },
                    { 'decks.groups': { $in: userWithAccess.groups }}
                ]}},
                { $project: {
                    decks: { $filter: {
                        input: '$decks',
                        as: 'deck',
                        cond: { $or: [
                            { $eq: ['$$deck.users', userWithAccess.name ]},
                            { '$$deck.groups': { $in: userWithAccess.groups }}
                        ]}
                    }}
                }}

Causes this error: (node:30398) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): MongoError: Unrecognized expression '$$deck.groups'

{ $match: { $or: [
                    { 'decks.users': userWithAccess.name },
                    { 'decks.groups': { $in: userWithAccess.groups }}
                ]}},
                { $project: {
                    decks: { $filter: {
                        input: '$decks',
                        as: 'deck',
                        cond: { $or: [
                            { $eq: ['$$deck.users', userWithAccess.name ]},
                            { $eq: ['$$deck.groups', userWithAccess.groups ]}
                        ]}
                    }}
                }}

Does not work unless the $$deck.groups is exact to the provided group array. Does not check within.

And it returns the entire deck object when I just want to return deck.name in the array. So the object return should be:

{
  user: 'name',
  decks: ['deck1', 'deck2', ...],
  ...
}

But I am getting:

{
  user: 'name',
  decks: [{...}, {...}, ...],
  ...
}

So that is why I am using $group and $unwind, it is returning what I want a lot more than $project.

Drew
  • 1,171
  • 4
  • 21
  • 36
  • @NeilLunn your duplicate link does not work for me, it is not returning the data I am asking for, it is similar and works in a very limited way. It does not check if decks.groups has any matching in the provided groups array. It does not return just the deck.name, it returns the whole deck. – Drew Aug 01 '17 at 23:11
  • You need to use `$map` in order to just select the `"name"` property from the array content instead of whole object present in the array. Added [duplicate for an answer showing that usage](https://stackoverflow.com/questions/45409849/select-matching-array-element-and-return-selected-fields/45430350#45430350) – Neil Lunn Aug 02 '17 at 01:50

0 Answers0