You could try the aggregation framework to achieve the desired results. The pipeline would need to make use of an initial $match operator that filters out the unwanted documents to get into the pipeline. Once you get the desired documents you would run multiple $unwind operators on the array fields to output a document for each element in the array fields for use in the next pipeline step. The following pipeline will need to filter the other documents from the deconstructed arrays using $match operator to then give you the required document. The last step of the pipeline, $project, then reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document. Thus the following pipeline will give you the result:
db.sites.aggregate([
{
"$match": {
"rooms.ups.batteryStrings._id": ObjectId("55dc967efefd4e6a14332019")
}
},
{ "$unwind": "$rooms" },
{ "$unwind": "$rooms.ups" },
{ "$unwind": "$rooms.ups.batteryStrings" },
{
"$match": {
"rooms.ups.batteryStrings._id": ObjectId("55dc967efefd4e6a14332019")
}
},
{
"$project": {
"siteName": 1,
"batteryStrings": "$rooms.ups.batteryStrings"
}
}
])
Running the pipeline operation would produce the result:
/* 0 */
{
"result" : [
{
"_id" : ObjectId("5613c98a645a64b1a70af2c1"),
"siteName" : "OGG",
"batteryStrings" : {
"name" : "String 1",
"ctrlId" : "bmstest11",
"_id" : ObjectId("55dc967efefd4e6a14332019"),
"batteries" : [
{
"name" : "String 2a",
"ctrlId" : "bmstest11",
"_id" : ObjectId("55e67b28010000880ca4c045")
},
{
"name" : "String 2b",
"ctrlId" : "bmstest11",
"_id" : ObjectId("55ea1b520100006d004e602a")
},
{
"name" : "String 2c",
"ctrlId" : "bmstest11",
"_id" : ObjectId("55ea1b520100006d004e602b")
}
]
}
}
],
"ok" : 1
}