Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving a specific embedded document from a MongoDB Query

Tags:

mongodb

I have a MongoDB document structured as

{
   "id": 1,
   "userId": 1,
   "layout": 1,
   "snapshotDetails": {
     "0": {
       "id": 1,
       "name": "jaison",
       "type": "justus",
       "width": 100,
       "height": 100,
       "position": 1 
    },
     "1": {
       "id": 2,
       "name": "jatin",
       "type": "justus",
       "width": 100,
       "height": 100,
       "position": 2 
    } 
  },
   "_id": ObjectId("4f58932309ac38f808000002") 
}

I need to extract the specific "1" embedded document under "snapshotDetails" like so:

"1": { "id": 2, "name": "jatin", "type": "justus", "width": 100, "height": 100, "position": 2 }

To do that I build a query something like this:

db.MasterDashboard.find({
"userId" : 1,
"snapshotDetails.id" : 1
},
{
"snapshotDetails" : 1
});

But i am not getting the output properly. The output of the query is

[
"0": {
       "id": 1,
       "name": "jaison",
       "type": "justus",
       "width": 100,
       "height": 100,
       "position": 1 
    },
     "1": {
       "id": 2,
       "name": "jatin",
       "type": "justus",
       "width": 100,
       "height": 100,
       "position": 2 
    }
] 

Can anyone spot the problem with this query and suggest how to just return the embedded document I want?

like image 650
Jaison Justus Avatar asked Dec 01 '25 06:12

Jaison Justus


2 Answers

This is a late answer but I think it will be useful for others. Supposing that snapshotDetails can be rewritten to be a proper array like:

{
    "_id" : ObjectId("4f58932309ac38f808000002"),
    "id" : 1,
    "userId" : 1,
    "layout" : 1,
    "snapshotDetails" : [ 
        {
            "id" : 1,
            "name" : "jaison",
            "type" : "justus",
            "width" : 100,
            "height" : 100,
            "position" : 1
        }, 
        {
            "id" : 2,
            "name" : "jatin",
            "type" : "justus",
            "width" : 100,
            "height" : 100,
            "position" : 2
        }
    ]
}

aggregate operations can be applied to slice, filter and reformat the document in any way needed. As an example, considering doc as the container collection, the following command would produce the desired result.

db.doc.aggregate([{$unwind:'$snapshotDetails'},{$project:{details:'$snapshotDetails' , _id:0}}, {$match:{'details.id':2}}])

Result:

{
    "result" : [ 
        {
            "details" : {
                "id" : 2,
                "name" : "jatin",
                "type" : "justus",
                "width" : 100,
                "height" : 100,
                "position" : 2
            }
        }
    ],
    "ok" : 1
}

More information at MongoDB Aggregations

like image 115
Fábio Avatar answered Dec 03 '25 19:12

Fábio


I think your issue is that it is returning the full content of the "snapshotDetails" sub-document, which is what the projection you are specifying is asking for. Try changing the projection you are using. I inserted your sample doc from above and then ran:

db.foo.find({"userId" : 1, "snapshotDetails.0.id" : 1}, 
            { "_id" : 0, "snapshotDetails.1" : 1})

Then it should only return the "1" sub-document, here's what I got as the output:

{ "snapshotDetails" : { "1" : 
                      { "id" : 2, 
                        "name" : "jatin", 
                        "type" : "justus", 
                        "width" : 100, 
                        "height" : 100, 
                         "position" : 2 
}}}
like image 42
Adam Comerford Avatar answered Dec 03 '25 18:12

Adam Comerford



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!