Rafael Rafael - 3 months ago 13
Node.js Question

MongoDB relational query

I'm new with mongo and still trying to drift my head away from the mySQL methodology and dive it into mongo, so a few things are still blur on how i'm suppose to do and i was hopping you guys could shed me some light.

Let me explain the problem. I'm using nodeJS and the mongodb native.

Say i have a collection of users (i've used simpler _id just to illustrate, i know its an objectID, but consider just for the sake of the example)

{
_id: 1,
name: 'John',
likes: ['2','3','4']
},
{
_id: 2,
name: 'Michelle'
likes: ['1','4']
},
{
name: 'Sabrina'
_id: 3,
likes: []
},
{
name: 'Simone'
_id: 4,
likes: ['1','2', '3']
}


note that John liked Michell, Sabrina, and Simone, that Michelle liked John and Simone, Sabrina didn't like anyone, and Simone liked John, Michelle and Sabrina.

How do i run a query for John to find out who also liked him back based on his array of likes? I need something that would return Michelle if id = 1, or returns John and Michelle if id = 4. Only the ones that the id i'm fetching is in the other users like.

let me try to simplify.

I need to fetch John and go through all his likes and check
id 2 likes me back? Yes
id 3 likes me back? No

return [John];

or fetch Simone and go through all her likes and check
id 1 likes me back? Yes
id 2 likes me back? Yes
id 3 likes me back? No

return [John, Michelle]

Any help would be appreciated :)
thanks

Answer

Here we go:

Something like this should do the trick using the mongodb-native driver in nodejs:

var people = db.collection("users");
people.findOne({name: "John"}, function(err, result)
  if(err) throw err; //..or however you want to handle an error.
  people.find({_id: {$in: result.likes}, likes:result._id}).toArray(function(err, others)
    {
    if(err) throw err; //...again, your call how to handle a potential error.
    //finds all people who are in likes array AND have Johns ID in their likes array.
    });
  });

Basically, first you retrieve the record for John. Next, you use his likes array to retrieve all users with matching id's :)

Note that this can be optimised slightly by opting to only retrieve the liked field for John, as in:

people.findOne({name: "John"}, {"likes": 1}, function(err, result)
  {
  //.....
  });

Also note that if the likes array is particularly massive, you may want to retrieve values one at a time rather than all at once using the .toArray() method, by instead using the cursor returned from find() and working with items one at a time, as in:

//....
var cursor = people.find({_id: {$in: result.likes}, likes:result._id});
cursor.each(function(err, item)
    {
    if(err) throw err; //...
    if(item != null)
    //do stuff with each person returned given likes array
    });
//....

I'm afraid I havnt tested the above, so apologies if I made any mistakes!

I find the manual for the mongo-native node.js driver to be invaluable; it covers most things pretty well (although some of the code seems a little "older" than other bits):

http://mongodb.github.io/node-mongodb-native/api-articles/nodekoarticle1.html

Comments