12

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 ^^

2 Answers 2

15

Try below query:

ListModel.findOne({"_id" : "57e6bcab6b383120f0395aed", 'recipients.status' : 1},{_id:1, name: 1, subject:1,'recipients.$': 1}, function(err,list){...});
Sign up to request clarification or add additional context in comments.

5 Comments

Both solutions worked for me ! Thanks sooo much for your help
@nicolas.grd Glad It helped!!
I like the clarity of this answer more than the accepted answer, both work.
Thank you for the answer. How can I proceed to delete this found object?
Thank you! I like your answer better, though all you needed was {'recipients.$': 1} for the second parameter. I get that this is a filter to limit the number of items to return.
6

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

2 Comments

This only returns a single $recipient, no matter how many answer the criteria.
I am getting error: Expected 0-2 arguments, but got 3.ts(2554) (property) 'recipients.status': number

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.