0

I'm very new to using Mongo and I have a collection that looks like this

{ 
    "_id" : "5e7a39ed-941a-4e07-af0b-df8764820206", 
    "title" : "Test Title Task", 
    "taskBody" : "This is a test task body", 
    "comments" : [
        {
            "_id" : "57b51a73-f585-4e80-ad51-107da707efd6", 
            "poster" : "Jack Black", 
            "comment" : "This is a comment"
        }, 
        {
            "_id" : "4ea314f3-3671-4568-b938-d8a1477ac681", 
            "poster" : "Joe Blow", 
            "comment" : "Another comment"
        }, 
        {
            "_id" : "c5f1a0e6-2fb9-429e-9931-8634f42fc143", 
            "poster" : "Mike Hall", 
            "comment" : " And yet Another comment"
        }
    ]
}

And I'm trying to get one of the comment elements by passing the ID like this:

getCommentById(id) {
        return tasks().then((taskCollection) => {
            return taskCollection.find({ "comments._id": id }).toArray().then((commentQuery) => {
                if (!commentQuery) throw "Comment not found";
                return commentQuery;
            });
        });
    }

However, it seems to be returning everything in the comments collection and not just one comment that I'm passing in the id for. How can I get it to return just the comment that I'm passing the id for?

This is what the debug window shows me

Array(1) [Object]
Object {_id: "5e7a39ed-941a-4e07-af0b-df8764820206", title: "Test Title Task", taskBody: "This is a test task body", …}

Array(3) [Object, Object, Object, …]
0: Object {_id: "57b51a73-f585-4e80-ad51-107da707efd6", poster: "Jack Black", comment: "Comment text 2"}

1: Object {_id: "4ea314f3-3671-4568-b938-d8a1477ac681", poster: "Joe Blow", comment: "Another comment"}

2: Object {_id: "c5f1a0e6-2fb9-429e-9931-8634f42fc143", poster: "Joe Blow", comment: "Another comment"}

What I'm expecting to get returned is just:

{
    "_id" : "57b51a73-f585-4e80-ad51-107da707efd6", 
    "poster" : "Jack Black", 
    "comment" : "This is a comment"
}

Assuming "57b51a73-f585-4e80-ad51-107da707efd6" is the passed in ID. Any help would be appreciated.

Community
  • 1
  • 1
Novice
  • 3
  • 1
  • 4

2 Answers2

3

You are querying sub array correctly. But your assumption is wrong. While you are querying with a specific sub document of an array field, a find query will still return a list of actual documents. You execute find on collection not just on an array field of a single document.

What you can do with mongoDB is this: you can exclude or include fields for your select queries. So you does not read unnecessary fields from mongoDB and it improves performance. You can learn more about this here

So for your question; while you just want to read a sub document in an array field, you have to use $ operator too. You can find more information here

Your query should look like this:

db.collection.find({ "_id": "some id", "comments._id": "some id"}, {"comments.$": 1, "_id": 0})

But again remember: This query will still return a list(or one collection if you use findOne) of your actual document, not a list of comment. Returned json will look like this:

{
  "comments": [
    {
      "_id" : "57b51a73-f585-4e80-ad51-107da707efd6", 
      "poster" : "Jack Black", 
      "comment" : "This is a comment"
    }
  ]
}

Note: If you really want just a comment with structure in your question. You can use aggregation and play the structure of json before return.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
barbakini
  • 3,024
  • 2
  • 19
  • 25
  • Thanks! That seemed to work! I got back [{"comments":[{"_id":"c993dfa7-d798-48ee-9e3f-bbbec8fcb564","poster":"John Doe","comment":"Test Comment by John Doe"}]}] I also tried the other suggestion taskCollection.find({ "comments": {$elemMatch: { _id: 'your value here '}}}) and that was returning the main task document and still every single comment – Novice Sep 07 '17 at 07:12
0
taskCollection.find({ "comments": {$elemMatch: { _id: 'your value here '}}})

This should work for you.

ManishKumar
  • 1,476
  • 2
  • 14
  • 22
  • 1
    already he is using `DOT` operation to retrieve from array, that should work , the query what he is posted is correct. ALso `elemMatch` will suit for multiple key conditions. – Subburaj Sep 07 '17 at 06:46