0

I have the below User document. I want to return a list of all 'friends' where friends.name is equal to "Bob".

{
    "_id" : ObjectId("5a4be9f200471a49d2e23ce4"),
    "name": "James"
    "friends" : [ 
        {
            "_id" : ObjectId("5a4be9f200471a49d2e23ce6"),
            "dob" : ISODate("2018-01-02T00:00:00.000Z"),
            "name" : "Bob"
        }, 
        {
            "_id" : ObjectId("5a4be9f200471a49d2e23ce5"),
            "dob" : ISODate("2018-01-02T00:00:00.000Z"),
            "name" : "Fred"
        }
    ],
    "__v" : 0
}

When I try to query using the below, its working but its returning the whole friends list, not just Bob.

  User.findOne({ "friends.name": "Bob" }, function(err, friends) {
        if(err) return next(err);
        res.send(friends);
      });

How can I query so I only to return Bob object and not Fred?

Starchand
  • 684
  • 1
  • 9
  • 23
  • 1
    https://stackoverflow.com/questions/36229123/return-only-matched-sub-document-elements-within-a-nested-array – Daniel Flippance Jan 03 '18 at 20:42
  • Possible duplicate of [Retrieve only the queried element in an object array in MongoDB collection](https://stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection) – s7vr Jan 03 '18 at 20:59

1 Answers1

1

Your query is correct, but it returns all user documents having at least one friend matching your condition.

If you just want matching items from the friends collection, you might do something like this.

db.User.aggregate([
  { $unwind: "$friends" },
  { $replaceRoot: { newRoot: "$friends" } },
  { $match: { name: "Bob" }}
])
Marcello
  • 879
  • 6
  • 20
  • 1
    This can be simplified using [$elemMatch(projection)](https://docs.mongodb.com/manual/reference/operator/projection/elemMatch/) to output the matching element in array. Something like`db.User.find( {"friends.name": "Bob"}, {"_id": 0, "friends": {"$elemMatch": {"name": "Bob"}}});`. – s7vr Jan 03 '18 at 22:35
  • The $elemMatch projection returns only the first matching element from the array. Should the User have more than one friend named Bob, you would see just the first one. Moreover, this way you are not returning friends, but the `friends` property of the User entity. – Marcello Jan 04 '18 at 07:43