1

I have a followSchema:

var followSchema = mongoose.Schema({ 
    user : { type: Number, ref: 'User'},
    following : { type: Number, ref: 'User'}
});

I have two users. Of the first one I need to have a list of all the users he follows. The second one I need to check if he already follows some of the users that I gathered from the first one.

How can I do this in an affective way in Mongoose. To get a list of followers from the first user isn't that hard, but to check if the second user follows one of them is a little harder and I have no idea how I can manage that.

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
Laurenswuyts
  • 2,144
  • 4
  • 21
  • 39

2 Answers2

2

This is fairly simple, all you need to do is query for the two conditions. Assuming "Follow" as the model:

Follow.find({
   "user": 1,
   "following": 2
})

Depending on your "scale" though, the following schema might be more useful:

var userSchema = new Schema({
    "_id": Number,
    "name": String,
    "following": [{ "type": Number, "ref": "User" }],
    "followedBy": [{ "type": Number, "ref": "User" }]
})

The query is almost identical:

User.find({
    "_id": 1,
    "following": 2
})

But of course it always gives you other options, as long as the general constraints for best practice with "arrays" can be adhered to.

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
  • If I use embedded documents then it doesn't scale that well, does it? If I have a user with millions of followers it gets kinda hard, no? – Laurenswuyts Mar 19 '15 at 11:42
1

One approach you can take is to modifying your followSchema to have the following field as an array and use the concept of population:

var mongoose = require('mongoose')
  , Schema = mongoose.Schema

var userSchema = Schema({
    _id: Number,
    name: String,
    age: Number,
    followers: [{ type: Schema.Types.ObjectId, ref: 'Follow' }]
});

var followSchema = Schema({
    _user: { type: Number, ref: 'User' },
    following: [{ type: Number, ref: 'User' }]
});

var Follow  = mongoose.model('Follow', followSchema);
var User = mongoose.model('User', userSchema);

which you can then query with the some sample users. As an example guide (untested):

var user1_id = 1,
    user2_id = 2,    
    user3_id = 3,   
    user1_following = [], 
    user2_following = [];

var user1 = new User({ _id: user1_id, name: 'User1', age: 31 });
var user2 = new User({ _id: user2_id, name: 'User2', age: 32 });
var user3 = new User({ _id: user3_id, name: 'User3', age: 32 });

user3.save(function (err) {
     if (err) return handleError(err);       
})

user1.save(function (err) {
     if (err) return handleError(err);  
     var follower3 = new Follow({ _user: user3_id });           
     follower3.save(function (err) {
        if (err) return handleError(err);
        // thats it!
     });
})

user2.save(function (err) {
     if (err) return handleError(err);  
     var follower3 = new Follow({ _user: user3_id });         
     follower3.save(function (err) {
        if (err) return handleError(err);
        // thats it!
     });
})

Follow
    .find({ _user: user1_id })
    .exec(function (err, following) {
         if (err) return handleError(err);
         user1_following = following;
   })    

Follow
    .find({ _user: user2_id })
    .exec(function (err, following) {
         if (err) return handleError(err);
         user2_following = following;
   }) 

You can then use Underscore's intersection() which will give you a list of values present in both arrays.

var commonFollowings = _.intersection(user1_following, user2_following);
// In the example above, commonFollowings => [3]
chridam
  • 100,957
  • 23
  • 236
  • 235
  • That means using an embedded document in followSchema? Right now I'm using multiple collections – Laurenswuyts Mar 19 '15 at 12:01
  • No, you will just be using references to documents in those multiple collections, which is the concept of Mongoose population. I have updated my answer to include a rough guideline as an example to your models. – chridam Mar 19 '15 at 12:34
  • Ok thanks, but if you have a lot of followers aren't you gonna exceed the 16mb limit? – Laurenswuyts Mar 19 '15 at 14:52
  • I think your question is best addressed with this [**answer**](http://stackoverflow.com/a/5373969/). – chridam Mar 19 '15 at 15:01