0

I have a mongodb Relationships collection that stores the user_id and the followee_id(person the user is following). If I query for against the user_id I can find all the the individuals the user is following. Next I need to query the Users collection against all of the returned followee ids to get their personal information. This is where I confused. How would I accomplish this?

NOTE: I know I can embed the followees in the individual user's document and use and $in operator but I do not want to go this route. I want to maintain the most flexibility I can.

brian Scroggins
  • 2,701
  • 3
  • 17
  • 17
  • Perhaps these two posts may push you in the right direction: [**Modelling the friend/following relationship**](https://groups.google.com/forum/#!topic/mongodb-user/tHyNMgDbfwM) and [**Twitter-like app using MongoDB**](http://stackoverflow.com/questions/4042917/twitter-like-app-using-mongodb). – chridam Oct 25 '15 at 21:07

2 Answers2

0

if i got your problem right(i think so).

you need to query each of the "individuals the user is following". that means to query the database multiple queries about each one and get the data. because the queries in node.js (i assume you using mongoose) are asynchronies you need to get your code more asynchronies for this task. if you not familier with the async module in node.js it's about time to know it. see npm async for docs. i made you a sample code for your query and how it needs to be.

/*array of followee_id from the last query*/
function query(followee_id_arr, callback) {
 var async = require('async')

 var allResults = [];
 async.eachSerias(followee_id_arr, function (f_id, callback){
  db.userCollection.findOne({_id : f_id},{_id : 1, personalData : 1},function(err, data){
   if(err) {/*handel error*/}
   else {
    allResults.push(data);
    callback()
   }
  }, function(){
   callback(null, allResults);
  })
 })
}

you can even make all the queries in parallel (for better preformance) by using async.map

Roi Tal
  • 121
  • 2
  • 8
  • Is this the only way. Does mongo not provide a way for you to query against a returned array? If that's not the case would you recommend embedding and array over this approach? I'm pretty new to mongo so i'm trying to understand the pros and cons – brian Scroggins Oct 25 '15 at 21:27
  • so if you want query on an array of the _id's it's even simpler: `db.usersCollection.find({_id :{$in : array_of _followee}}, {_id : 1, personalData : 1}, callback)` – Roi Tal Oct 25 '15 at 22:07
0

You can use an $in query without denormalizing the followees on the user. You just need to do a little bit of data manipulation:

Relationship.find({user_id: user_id}, function(error, relationships) {

    var followee_ids = relationships.map(function(relationship) {
        return relationship.followee_id;
    });

    User.find({_id: { $in: followee_ids}}, function(error, users) {
        // voila
    });
};
chrisbajorin
  • 5,993
  • 3
  • 21
  • 34
  • I'm going to try this solution in a little – brian Scroggins Oct 25 '15 at 23:45
  • One last question, would you embed the friends into one document? It seems to me like this will ultimately scale very poorly not to mention mongos document limit – brian Scroggins Oct 26 '15 at 11:10
  • No I wouldn't. What I showed above is a fairly standard design pattern I use. The "never do this" of mongo/nosql is to have a potentially unlimited array. – chrisbajorin Oct 26 '15 at 13:30
  • @brianScroggins To clarify part of my previous comment; "fairly standard" means that I use it where necessary but I don't design my app around using it. If this is used all over the place, take some time to reconsider the architecture of your data. e.g if you're doing this just to grab the followee emails, you can just denormalize that information on the Relationship model, making that second query unnecessary. It's more susceptible to programmer error, but it's faster reads and errors are what tests are for :) here's an answer I wrote regarding that http://stackoverflow.com/a/30194540/3696076 – chrisbajorin Oct 26 '15 at 17:28