Reputation: 43
I want to query mongodb document to return a specific document
Suppose I have the below document and I want to search only the specific details of a given room. Say, I want query to return notes for room_num = 210. How do I do it?
I was able to query by db.locations.findOne({"facility.room.room_num" : room_num}); I don't know how to project room only. Generalizing the question, how do I project only the embedded document specific entries only.
My document looks like this --->
{
_id: Object("xxx"),
name: "Campus",
facilities: [
{ name : "Science",
rooms : [
{
room_num: 210,
notes: "Chemistry Lab 1",
Dimension: "x*x"
},{
room_num: 120,
notes: "Chemistry Lab 2",
Dimension: "x*x"
}
]
},
{ name : "Arts",
rooms: [
{
room_num: 90,
notes: "Drawing 1",
Dimension: "x*x"
},{
room_num: 100,
notes: "Drawing 2",
Dimension: "x*x"
}
]
}
]
Upvotes: 2
Views: 242
Reputation: 151072
Since you have an embedded array (one within another) then you can indeed do this with aggregate. You just need to do a "double" unwind operation:
db.collection.aggregate([
{ "$unwind": "$facilities" },
{ "$unwind": "$facilities.rooms" },
{ "$match": { "facilities.rooms.room_num": 210 } }
])
And if you really want it to look like the original document, then take it a little further:
db.collection.aggregate([
{ "$unwind": "$facilities" },
{ "$unwind": "$facilities.rooms" },
{ "$match": { "facilities.rooms.room_num": 210 } },
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"facName": { "$first": "$facilities.name" },
"rooms": { "$push": "$facilities.rooms" }
}},
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"facities": { "$push": {
"name": "$facName" ,
"rooms": "$rooms"
}}
}}
])
So from your data this would be the result:
{
"_id" : {
"0" : "x",
"1" : "x",
"2" : "x"
},
"name" : "Campus",
"facities" : [
{
"name" : "Science",
"rooms" : [
{
"room_num" : 210,
"notes" : "Chemistry Lab 1",
"Dimension" : "x*x"
}
]
}
]
}
Or finally if all you need is the inner rooms part of the arrays, then just use a $project
statement at the end, as from the first example:
db.campus.aggregate([
{ "$unwind": "$facilities" },
{ "$unwind": "$facilities.rooms" },
{ "$match": { "facilities.rooms.room_num": 210 } },
{ "$project": {
"_id": 0,
"room_num": "$facilities.rooms.room_num",
"notes": "$facilities.rooms.notes",
"Dimension": "$facilities.rooms.Dimension"
}}
])
With a result like this:
{ "room_num" : 210, "notes" : "Chemistry Lab 1", "Dimension" : "x*x" }
And that should clear it up.
Upvotes: 1
Reputation: 4173
You can make use of the aggregation framework. I believe the $project and $unwind operators are what you are looking for.
db.rooms.aggregate([{
$project: {
_id: 0,
facilities: "$facilities.rooms.room_num"
}
}, {
$unwind: "$facilities"
}, {
$unwind: "$facilities"
}])
and you would get something like:
{
"result" : [
{
"facilities" : 210
},
{
"facilities" : 120
},
{
"facilities" : 90
},
{
"facilities" : 100
}
],
"ok" : 1
}
Upvotes: 0
Reputation: 2354
Try the below query
db.locations.aggregate(
{ $unwind: "facilities.rooms" },
{ $match: { "facilities.rooms.room_num" : room_num}},
{ $project: { "facilities.rooms.notes" : 1 }}
)
Upvotes: 0