0

In my mongodb (using Mongoose), I have story collection which has comments sub collection and I want to query the subdocument by client id, as

Story.find({ 'comments.client': id }, { title: 1, 'comments.$': 1 }, function (err, stories) {
    ...
    })
})

The query works except that it only returns the first matched subdocument, but I want it to return all matching subdocuments. Did I miss an option?

EDIT:

On Blakes Seven's tip, I tried the answers from Retrieve only the queried element in an object array in MongoDB collection, but I couldn't make it work.

First tried this:

Story.find({'comments.client': id}, { title: 1, comments: {$elemMatch: { client: id } } }, function (err, stories) {

})

It also returns the first match only.

Then, I tried the accepted answer there:

Story.aggregate({$match: {'comments.client': id} }, {$unwind: '$comments'}, {$match : {'comments.client': id} }, function (err, stories) {

})

but this returns nothing. What is wrong here?

UPDATE:

My data structure looks like this:

{
    "_id" : ObjectId("55e2185288fee5a433ceabf5"),
    "title" : "test",
    "comments" : [ 
        {
            "_id" : ObjectId("55e2184e88fee5a433ceaaf5"),
            "client" : ObjectId("55e218446033de4e7db3f2a4"),
            "time" : ISODate("2015-08-29T20:16:00.000Z")
        }
    ]
}
Community
  • 1
  • 1
newman
  • 6,841
  • 21
  • 79
  • 126
  • 1
    possible duplicate of [Retrieve only the queried element in an object array in MongoDB collection](http://stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection). See answers using aggregagte – Blakes Seven Aug 29 '15 at 22:39
  • 1
    I just tried in the mongo shell with test data conforming to your example data structure and I received all records. The command I used: `db.exampleC.aggregate([ { $unwind : "$comments" }, { $match : { "comments.client" : ObjectId("55e218446033de4e7db3f2a4") } } ])`. (My example collection is called `exampleC` and the comments.client value is `ObjectId("55e218446033de4e7db3f2a4")`. Note, I left off the first `$match` for brevity; can explain why if needed.) Did you try in the shell? Is the correct `id` value being passed in? – whyceewhite Aug 30 '15 at 01:20
  • @whyceewhite Okay, with your tip by running it in shell, I figured out why my original code didn't work. The problem is that my "id" is actually a string (from client), for other queries like "find", mongoose seems to convert it automatically, but "aggregate" doesn't do it. Once I convert id to objectId, it works. Thank you very much. – newman Aug 30 '15 at 04:43
  • @whyceewhite, Once I made it work using aggregate, I see another problem. Unlike using $, the aggregate doesn't return the parent document (story). Is there a way to include the parent document? – newman Aug 30 '15 at 04:49
  • By parent document, you mean that you want to include the `_id` and `title` fields in the results as well? If yes then those values **do** come back in the shell. Perhaps mongoose does something different? – whyceewhite Aug 30 '15 at 14:25
  • @whyceewhite, ah, you are right. I overlooked it - sorry. By the way, is there a way to filter out some fields? For example, I have a content field in story which could be large and I don't need it for this query. – newman Aug 30 '15 at 18:13
  • Use `$project`. See [this](http://docs.mongodb.org/manual/reference/operator/aggregation/project/) mongo documentation. – whyceewhite Aug 31 '15 at 01:08
  • Got it. too bad I can't exclude any field other than _id. Thank you very much. – newman Aug 31 '15 at 02:37

0 Answers0