4

I have a schema design question. I have a UserSchema and a PostSchema.

var User = new Schema({ name: String }); var Post = new Schema({ user: { type: Schema.Types.ObjectId } }); 

Also, user is able to follow other users. Post can be liked by other users. I would like to query User's followers and User's following, with mongoose features such as limit, skip, sort, etc. I also want to query Post that a user likes.

Basically, my only attempt of solving this is to keep double reference in each schema. The schemas become

var User = new Schema({ name: String, followers: [{ type: Schema.Types.ObjectId, ref: "User" }], following: [{ type: Schema.Types.ObjectId, ref: "User" }] }); var Post = new Schema({ creator: { type: Schema.Types.ObjectId, ref: "User" }, userLikes: [{ type: Schema.Types.ObjectId, ref: "User" }] }); 

so, the code that will be used to query

// Find posts that I create Post.find({creator: myId}, function(err, post) { ... }); // Find posts that I like Post.find({userLikes: myId}, function(err, post) { ... }); // Find users that I follow User.find({followers: myId}, function(err, user) { ... }); // Find users that follow me User.find({following: myId}, function(err, user) { ... }); 

Is there a way other than doing double reference like this that seems error prone?

1 Answer 1

4

Actally, you don't need the double reference. Let's assume you keep the following reference.

var User = new Schema({ name: String, following: [{ type: Schema.Types.ObjectId, ref: "User" }] }); 

You can use .populate() to get the users you're following:

EDIT: added skip/limit options to show example for pagination

User.findById(myId).populate({ path:'following', options: { skip: 20, limit: 10 } }).exec(function(err, user) { if (err) { // handle err } if (user) { // user.following[] <-- contains a populated array of users you're following } }); 

And, as you've already mentioned ...

User.find({following: myId}).exec(function(err, users) { ... }); 

... retrieves the users that are following you.

Sign up to request clarification or add additional context in comments.

4 Comments

Yes I can use populate. However, imagine if I have a lot of users. Then if I populate that, and send those to the front end, it will be a lot of data. I am thinking of more on how to implement pagination / infinite scrolling.
You should have stated so in your original question. You can't expect a solution that fits your needs if you don't specify your needs. That said, there's no reason you can't implement a pagination/infinite scrolling solution using the answer above as your starti point. How to implement such a solution, however, is beyond the scope of your question.
Ok, sorry for that. How do I implement pagination using your solution? Because on standard query, I can just do limit and skip, but with populate, there is no such option.
.populate() has skip and limit options you can use to implement paging. I will update my answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.