Twinsen
Twinsen

Reputation: 893

Retrieve a specific field Mongoose

I want retrieve the account array if the query find role "elite"

i try with

db.users.aggregate(
{ $match : { "account.role" : "Elite" } }
);

But i have all object...

{
"_id" : ObjectId("7623902143981943"),        
"account" : [ 
    {
        "role" : "Elite",            
        "action" : [ 
            "create", 
            "read", 
            "update", 
            "delete"
        ],
        "extra" : {
            account:[1,2,3,4]
        }
    },
 {
        "role" : "User",            
        "action" : [ 
            "create", 
            "read", 
            "update", 
            "delete"
        ],
        "extra" : {
            account:[10]
        }
    }
],    

}

Can i retrieve only extra Array ( account:[1,2,3,4] ),if it is a positive result from the query? or I have to parse the received object? (the schema is very simplified, but I have many roles)

Upvotes: 0

Views: 326

Answers (1)

Enrique Fueyo
Enrique Fueyo

Reputation: 3488

You must use $project and $unwind:

//Order of $unwind and $match matters
db.users.aggregate(
 {$unwind: "$account"},
 {$match : { "account.role" : "Elite" }},
 {$project : { "extra.account" : 1}}
);

explanation

$unwind splits the array into different elements. See the effect of

 db.users.aggregate({$unwind: "$account"})

then you match the elements with {"account.role": "Elite"}. See the effect of:

db.users.aggregate(
 {$unwind: "$account"},
 {$match : { "account.role" : "Elite" }}
);

And then you finally project just the desired fields

db.users.aggregate(
 {$unwind: "$account"},
 {$match : { "account.role" : "Elite" }},
 {$project : { "extra.account" : 1}}
);

//You can also remove the _id filed (included by default with:
db.users.aggregate(
 {$unwind: "$account"},
 {$match : { "account.role" : "Elite" }},
 {$project : { _id: 0, "extra.account" : 1}}
);

OLD ANSWER

You must use projection: db.users.aggregate( {$match : { "account.role" : "Elite" }}, {$project : { "extra.account" : 1}} );

Besides, if you are just matching documents, there's no need to use the aggregation framewrok and you can just use:

// No projection here
db.users.find({"account.role" : "Elite"})

or

// Only returns the _id field + "extra.account" field if exists. By default the _id field is included
db.users.find({"account.role" : "Elite"}, { "extra.account" : 1}) 

// Only returns the "extra.account" field if exists
db.users.find({"account.role" : "Elite"}, { _id: 0, "extra.account" : 1}) 

Mongodb documentation can be found here and here

Upvotes: 1

Related Questions