1
{
   "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?

2 Answers 2

3

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
}
Sign up to request clarification or add additional context in comments.

Comments

1

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" } ] }

3 Comments

very nice solution. Didn't knew that :)
it returns { "refs" : [ { }, { } ] } on my server. My mongo version is 2.0.2. Could it be the problem?
@gzg Yes, the use of $ in a projection was added in 2.2.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.