1
{
_id: ObjectId("52ca2d45b80de42808000001"),
id: "1111139048239",
name: "Bruce Lim",
first_name: "Bruce",
last_name: "Lim",
friends: [
    {
        id: "1913681",
        name: "John Sim",
        icon: "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-ash2/1117702_1913681_1171369396_q.jpg",
        photos: [
            {
                src: "https://scontent-a.xx.fbcdn.net/hphotos-ash2/t1/230718_10150181312510976_7606555_n.jpg",
                lat: "38.2289",
                lng: "-85.7495"
            },
            {
                src: "https://scontent-b.xx.fbcdn.net/hphotos-frc3/230480_10150181312620976_3864544_n.jpg",
                lat: "38.2289",
                lng: "-85.7495"
            }
        ]
    },
    {
        id: "31925743892",
        name: "Mike Holloway",
        icon: "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-prn2/211634_31925743892_1471358831_q.jpg",
        photos: [
            {
                src: "https://scontent-a.xx.fbcdn.net/hphotos-ash2/t1/230718_10150181312510976_7606555_n.jpg",
                lat: "38.2289",
                lng: "-85.7495"
            },
            {
                src: "https://scontent-b.xx.fbcdn.net/hphotos-frc3/230480_10150181312620976_3864544_n.jpg",
                lat: "38.2289",
                lng: "-85.7495"
            }
        ]
    },
    {
        id: "1954048",
        name: "Christiana Basset",
        icon: "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-prn2/211634_1954048_1471358831_q.jpg",
        photos: [
            {
                src: "https://scontent-a.xx.fbcdn.net/hphotos-ash2/t1/230718_10150181312510976_7606555_n.jpg",
                lat: "38.2289",
                lng: "-85.7495"
            },
            {
                src: "https://scontent-b.xx.fbcdn.net/hphotos-frc3/230480_10150181312620976_3864544_n.jpg",
                lat: "38.2289",
                lng: "-85.7495"
            }
        ]
    }
]

}

when I query a collection of these docs this with

db.mapping.find(
    {"id":"1111139048239"},
    {"friends":{
        $elemMatch:{"id":"1913681"}
    }}
)

I get one matching friend subset back.

{
        "_id" : ObjectId("52ca2d45b80de42808000001"),
        "friends" : [
                {
                        "id" : "1913681",
                        "name" : "John Sim",
                        "icon" : "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-ash2/1117702_1913681_1171369396_q.jpg",
                        "photos" : [
                                {
                                        "src" : "https://scontent-a.xx.fbcdn.net/hphotos-ash2/t1/230718_10150181312510976_7606555_n.jpg",
                                        "lat" : "38.2289",
                                        "lng" : "-85.7495"
                                },
                                {
                                        "src" : "https://scontent-b.xx.fbcdn.net/hphotos-frc3/230480_10150181312620976_3864544_n.jpg",
                                        "lat" : "38.2289",
                                        "lng" : "-85.7495"
                                }
                        ]
                }
        ]
}

How do I select multiple subsets.

db.mapping.find(
    {"id":"1111139048239"},
    {"friends":{
        $elemMatch:{"id":"1913681", "id":"1954048"}
    }}
)

db.mapping.find(
    {"id":"1111139048239"},
    {"friends":{
        $elemMatch:{"id":"1913681"},
        $elemMatch:{"id":"1954048"}
    }}
)

gets me only the last match, which is 1954048 in this case. How do I get both - 1913681, 1954048?

Bruce Lim
  • 745
  • 6
  • 22
  • `$elemMatch` only returns the first matching element in an array. To match multiple elements you will have to use the Aggregation Framework. For an example of this see: [Only extract selected element in an array](http://stackoverflow.com/questions/3985214/mongodb-extract-only-the-selected-item-in-array/12241733#12241733). – Stennie Jan 06 '14 at 05:31

1 Answers1

2

The general syntax of find in mongodb is

db.collection.find(<criteria>,<projection>)

In your case,

 criteria: id should be "1111139048239"
 projection: listing friends who have id 1913681, 1954048

elemMatch can get only the first existence of the element and also when multiple values are given for same attribute it will display only the last executed elemMatch within the document.

I would suggest you to go with aggregation. It will help you to get the required output.

db.mapping.aggregate([
          {$match:{id:"1111139048239"}}, // STEP 1
          {$unwind:"$friends"}, // STEP 2 
          {$match:{"friends.id":{$in:["1913681","1954048"]}}} // STEP 3
                    ])

Execution:

 STEP 1: Selects the document with id "1111139048239"
 STEP 2: Unwinds the friends array in the selected document and 
         create multiple documents as per the size of friends array.
         In this case 3 documents.
 STEP 3: Select documents which has a friends id "1913681", "1954048".
         In this case 2 documents will be selected. Append values to array to get
         more documents as output
         {"friends.id":{$in:["1913681","1954048",etc]}
Amarnath Krishnan
  • 1,253
  • 1
  • 9
  • 12
  • I tried something along the lines of this and was getting the entire document back before. Thank you for explaining the steps in detail about the unwind step. – Bruce Lim Jan 06 '14 at 17:56