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
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
It has to be done in two queries (since Mongo is non-relational). The fist query would be to get the person (I'm sure you've figured out how to do that). The second would answer who likes him/her back.
var userId = 1;
people.findOne({ _id: userId }, { likes: 1 }, function (err, person) {
if (err)
throw err; // <-- obviously handle the error better than this
people.find({ _id: { $in: person.likes }, likes: userId }).toArray(
function (err, likers) {
//now you have your list of people who liked the user back
}
);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With