1

I have three models: User, Post and Comment

var User = new Schema({
    name: String,
    email: String,
    password: String // obviously encrypted
});

var Post = new Schema({
    title: String,
    author: { type: Schema.ObjectId, ref: 'User' }
});

var Comment = new Schema({
    text: String,
    post: { type: Schema.ObjectId, ref: 'Post' },
    author: { type: Schema.ObjectId, ref: 'User' }
});

I need to get all posts in which the user has commented.

I know it should be a very simple and common use case, but right now I can't figure a way to make the query without multiple calls and manually iterating the results.

I've been thinking of adding a comments field to the Post schema (which I'd prefer to avoid) and make something like:

Post.find()
    .populate({ path: 'comments', match: { author: user } })
    .exec(function (err, posts) {
        console.log(posts);
    });

Any clues without modifying my original schemas?

Thanks

1 Answer 1

1

You have basically a couple of approaches to solving this.

1) Without populating. This uses promises with multiple calls. First query the Comment model for the particular user, then in the callback returned use the post ids in the comments to get the posts. You can use the promises like this:

var promise = Comment.find({ "author": userId }).select("post").exec();
promise.then(function (comments) {
    var postIds = comments.map(function (c) {
        return c.post;
    });
    return Post.find({ "_id": { "$in": postIds }).exec();
}).then(function (posts) {
    // do something with the posts here
    console.log(posts);

}).then(null, function (err) {
    // handle error here
});

2) Using populate. Query the Comment model for a particular user using the given userId, select just the post field you want and populate it:

var query = Comment.find({ "author": userId });
query.select("post").populate("post");
query.exec(function(err, results){    
    console.log(results);
    var posts = results.map(function (r) { return r.post; });
    console.log(posts);
}); 
Sign up to request clarification or add additional context in comments.

2 Comments

Looks promising (no pun intended), but it's exactly what I'm referring to in my post when I say I'm finding a way to avoid multiple calls (there are two finds) and iterating (map).
@javorosas Updated my answer with another approach which doesn't require multiple calls but manipulates the results array to return just the posts, closer to what you are looking for.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.