Q: querying mongodb with nested where conditions {
   "name": "comments",
   "rid": 456,

   "refs": [
     {
       "no": 1,
       "info": "this is first"  
    },
     {
       "no": 2,
       "info": "this is second" 
    },
     {
       "no": 3,
       "info": "this is third"  
    } 
  ] 
}
{
   "name": "comments",
   "rid": 321,

   "refs": [
     {
       "no": 1,
       "info": "this is first-h"  
    },
     {
       "no": 2,
       "info": "this is second-h" 
    },
     {
       "no": 3,
       "info": "this is third-h"  
    } 
  ] 
}

Assume I have a document structure like above. I need to get the array whose rid is 456 and no is 2. So, I just want to get the array
     {
       "no": 2,
       "info": "this is second" 
    }

How could I do that?

A: In addition to JohnnyHK's use of the positional operator, there are a few more ways to approach this in MongoDB 2.2+:
Approach #1: use an $elemMatch projection
The $elemMatch projection can be used to include a single matching element of an array.  By default the result also includes the document _id, but you can exclude this if not needed:
db.comments.find(
    { rid: 456 },
    { _id:0, refs: { $elemMatch: { no: 2 } }}
)

Example output:
{ "refs" : [ { "no" : 2, "info" : "this is second" } ] }

Approach #2: use the Aggregation Framework
The Aggregation Framework includes operators to $unwind arrays and $match document criteria.  This approach has more flexibility than using an $elemMatch projection, because multiple matches per array can now be returned.
db.comments.aggregate(

    // Find matching documents of interest (can use an index)
    { $match: { rid: 456 }},

    // Create stream of documents based on the `refs` array
    { $unwind: "$refs" },

    // Match the specific refs element(s) of interest
    { $match: { "refs.no" : 2 }},

    // Project the desired output
    { $project: {
        _id: 0,
        no: "$refs.no",
        info: "$refs.info"
    }}
)

Example output:
{
    "result" : [
        {
            "no" : 2,
            "info" : "this is second"
        }
    ],
    "ok" : 1
}


A: You can use dot notation to find the document you want, and the $ position operator to include just the matched array element in the result:
 db.test.find({rid: 456, 'refs.no': 2}, {_id: 0, 'refs.$': 1})

returns:
{ "refs": [ { "no": 2, "info": "this is second" } ] }

