its me
its me

Reputation: 542

How do I query documents where an entry in a sub-array matches all conditions?

Below is my rolesandresponsibilities collection document's

[{
    "_id": {
        "$oid": "58b6c380734d1d48176c9e69"
    },
    "role": "Admin",
    "resource": [
        {
            "id": "blog",
            "permissions": [
                "read",
                "update",
                "delete"
            ]
        },
        {
            "id": "user",
            "permissions": [
                "create",
                "read",
                "update",
                "delete"
            ]
        },
        {
            "id": "journal",
            "permissions": [
                "create",
                "read",
                "update",
                "delete"
            ]
        }
    ]
},
{
    "_id": {
        "$oid": "58b7db3cf36d285019ea175f"
    },
    "role": "Manager",
    "resource": [
        {
            "id": "blog",
            "permissions": [
                "read",
                "update",
                "delete"
            ]
        },
        {
            "id": "user",
            "permissions": [
                "create",
                "read",
                "update",
                "delete"
            ]
        },
        {
            "id": "journal",
            "permissions": [
                "create",
                "read",
                "update",
                "delete"
            ]
        }
    ]
}]

I want to check Admin has create access or not. I have written query like this

var check = { $and: [ { 'role':req.body.role, },  { 'resource.id':'blog'},{'resource.permissions':'create'} ] }
Rolesandresponsibilitie.find(check).populate('user', 'displayName').exec(function(err, rolesandresponsibilities) {
        if (err) return next(err);
        if (! rolesandresponsibilities) return res.status(404).send('Not Found'); };
        return res.status(200).send('Found'); }

    });

I am Getting Undefined

MY Expectation :

for example 1:

role = Admin

id = blog

permissions = create

i should get response Not Found because Admin has only

"permissions": [ "read", "update", "delete" ]

above 3 permissions

example 2 :

role = Admin

id = blog

permissions = read

i should get response Found because Admin has read permission

Upvotes: 0

Views: 48

Answers (2)

Andy Macleod
Andy Macleod

Reputation: 3069

$elemMatch is what you need and it will simplify the query. By default mongo will treat properties in the query as an $and statement so there is no need to add that here.

A simpler query would be

var check = {
    'role':req.body.role,
    'resource':{
        '$elemMatch': {
            'id': 'blog',
            'permissions': 'create'
        }
     }
}

Rolesandresponsibilitie.find(check).populate('user', 'displayName').exec(function(err, rolesandresponsibilities) {
    if (err) return next(err);
    if (! rolesandresponsibilities) return res.status(404).send('Not Found'); };
    return res.status(200).send('Found'); }

});

The current issue you are having is because querying on

'resource.id':blog and 'resource.permissions':create

is that you have elements in the array that match both filters. It simply checks the resource array to se if something has id=blog and if something has permissions=create, and the results don't necessarily have to be the same entry in the array.

Best of luck!

Upvotes: 2

Puneet Singh
Puneet Singh

Reputation: 3543

You need to use $elemMatch if you want to query in an array of sub documents, and you want to put condition per sub document basis.

var check = { $and: [ { 'role':req.body.role, },  { resource: { $elemMatch: { 'id': 'blog', 'permissions': 'create' } } }  ] }

Change the condition as mentioned above.

Upvotes: 1

Related Questions