nicolas.grd nicolas.grd - 2 months ago 19
Node.js Question

Mongoose :Find and filter nested array

I'm trying to find a whole document with

Find()
command and filter a nested array with a condition.

Here a piece of the used Schema :

var ListSH = new Schema({
name: { type: String, unique: true, required: true},
subject : String,
recipients : [
Schema({
uid : { type : ObjectId, required : true, ref:'User', unique: true},
status : { type : Number, default : 1 }
},{_id: false})
]
};


Currently I do
ListModel.findOne({ _id : req.params.id_list, function(err,list){...};


And Postman give me that:

{
"_id": "57e6bcab6b383120f0395aed",
"name": "Emailing listname",
"subject": "List subject",
"recipients": [
{
"uid": "57e932bcbbf0e9e543def600",
"status": 0
},
{
"uid": "57e93266c3c0b1dc1625986f",
"status": 1
}
]
}


I'd like Postman to return me something like that by adding a
recipients.status : 1
condition

{
"_id": "57e6bcab6b383120f0395aed",
"name": "Emailing listname",
"subject": "List subject",
"recipients": [
{
"uid": "57e93266c3c0b1dc1625986f",
"status": 1
}
]
}


I've already tried
ListModel.findOne({ _id : req.params.id_list, 'recipients.status' : 1}, function(err,list){...};


and something weird like
populate([$match('recipients.status : 1)]);

but with no success..

Anyone knows ?
Thanks ^^

Answer

You can use aggregate to get it in an easy way like this

ListModel.aggregate(
    { $match: {_id: ObjectId("57e6bcab6b383120f0395aed")}},
    { $unwind: '$recipients'},
    { $match: {'recipients.status':1}})

Output

{
    "_id" : ObjectId("57e6bcab6b383120f0395aed"),
    "name" : "Emailing listname",
    "subject" : "List subject",
    "recipients" : {
        "uid" : "57e93266c3c0b1dc1625986f",
        "status" : 1
    }
}

To understand aggregation in details see the docs here