1

I cannot show all`, if some value are in array property in mongo document. For example, I have some collection users, and such document:

This is collection friend

'list': [
{
  '_id': '123',
  'name':'Charlie',
  'age':50,
},
{
  '_id': '234',
  'name':'Micheal',
  'age':32,
},
{
  '_id': '345',
  'name':'Alice',
  'age':45,
}
]

This is collection seft

'name':'Paul',
  'age':43,
  'friends': 
    [
        {  '$ref': 'friend',
           '$id': 123},
        {  '$ref': 'friend',
           '$id': 234},
        {  '$ref': 'friend',
           '$id': 345}
    ],

Now, let's suppose that I want to query "show all friends of Paul" like:

{
  'name':'Paul',
  'age':43,
  'friendsIDs': 
  'friends': 
    [
        {  '_id': '123',
           'name':'Charlie',
           'age':50 },
        {  '_id': '234',
           'name':'Micheal',
           'age':32},
        {  '_id': '345',
           'name':'Alice',
           'age':45 }
    ]
}
1
  • This needs to be done in your application layer, MongoDB doesn't support join. Commented May 6, 2015 at 3:30

1 Answer 1

2

MongoDB doesn't support joins. You can read more about that here.

However, you can manually reproduce the same scenario you described above in MongoDB by using some native JavaScript functions to fill in the friends array with the references and save the modified data to another collection say self_friends.

Let's demonstrate this by using the above schema. Insert the sample data in two collections self and friends:

// Populate self collection
db.self.insert([
    {
        'name':'Paul',
        'age':43,
        'friends': 
        [
            {  '$ref': 'friend',
               '$id': 123},
            {  '$ref': 'friend',
               '$id': 234},
            {  '$ref': 'friend',
               '$id': 345}
        ]
    }    
]);

// Populate friends collection
db.friends.insert([
    {
      '_id': '123',
      'name':'Charlie',
      'age':50,
    },
    {
      '_id': '234',
      'name':'Micheal',
      'age':32,
    },
    {
      '_id': '345',
      'name':'Alice',
      'age':45,
    }
]);

The following operation will populate another collection self_friends with the desired result:

db.self.find({"name" : "Paul"}).forEach(function(doc){
        var friends = doc.friends.map(function(f){
            //var friend = db.friends.findOne({_id: f["$id"].toString()})
            // Or use @SylvainLeroux's brilliant suggestion 
            var friend = db.getCollection(f["$ref"]).findOne({_id: f["$id"].toString()})
            return friend;
        });
        doc.friends = friends;
        db.self_friends.save(doc);
})

Querying the db.self_friends collection with db.self_friends.find() will give the result:

/* 0 */
{
    "_id" : ObjectId("5549f2ff180e849972939047"),
    "name" : "Paul",
    "age" : 43,
    "friends" : [ 
        {
            "_id" : "123",
            "name" : "Charlie",
            "age" : 50
        }, 
        {
            "_id" : "234",
            "name" : "Micheal",
            "age" : 32
        }, 
        {
            "_id" : "345",
            "name" : "Alice",
            "age" : 45
        }
    ]
}
Sign up to request clarification or add additional context in comments.

2 Comments

Given the OP document stores DBRef, maybe you should use something like db.getCollection(f["$ref"]).findOne({_id: f["$id"].toString()}) -- that being said, I don't think there is any benefit in using DBRef here instead of plain id. Or is it ?
@SylvainLeroux That's a great suggestion actually, would make much more sense to use the $ref key to get the collection with the value. I also would concur it wont be too beneficial to use DBRefs in the case above as the _ids are stored as strings in the reference collections.

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.