user3766930
user3766930

Reputation: 5829

How can I merge results into a single JSON while querying data from two different models in node.js and mongoose?

I have two mongoose models in my app:

var UsersSchema = new Schema({
    username: {type: String},
    facebook_username: {type: String},
    display_name: {type: String}
}

and

var CommentsSchema = new Schema({
    user_id: {type: String, required: true},
    text_content: {type: String},
    photo_content_url: {type: String}
    comment_date: {type: Date, default: Date.now},
    created_at: {type: Date, default: Date.now},
}

currently each single comment contains user_id - a direct link to its author.

I created a node.js endpoint that takes POST query and returns JSON with all details about comments:

commentsRoutes.post('/comments', function (req, res) {

    var startDate = req.body.startDate;
    var endDate = req.body.endDate;

    var query= {};
    query.$and = [];

    // and condition on start date
    if(startDate != undefined) {
        var startDate = new Date(req.param('startDate'));
        var endDate = new Date(req.param('endDate'));
        query.$and.push({"comment_date":{$gte: startDate}});
        query.$and.push({"comment_date":{$lte: endDate}});
    }

    var finalquery = Comments.find(query)
    finalquery.exec(function(err, comments){
        if(err) {
            res.send(err);
            return;
        }
        res.json(comments);
    });
});

This endpoint returns me a JSON with all the comments, however - I need to attach to each JSON details about its author - username, facebook_username and display_name (fetched based on user_id from UsersSchema). Can you tell me how could I do it?

user_id in CommentsSchema is a mongoose id of a specific user from UsersSchema

====== EDIT

Like @Antonio suggested in his answer below, I used populate in my case, it worked well and I saw merged JSON at the end. All user details were added, it looked like:

{ 
  "text_content": "blah",
  "photo_content_url": "http://www...",
  "comment_date": "some date",
  "created_at": "some date",
  "user_id": { "username": "someUsername",
               "facebook_username": "fbUsername",
               "display_name": "sth" }
}

however - is there a way to include POST parameters in my endpoint that will apply to the user_id json?

Currently I'm sending a POST parameters startDate and endDate. But if I send also facebook_username - how can I include it in a query and find only comments that were written by this author?

I tried adding a simple condition:

var fb_username = req.body.facebookUsername;
query.$and.push({"facebook_username": fb_username});

but it didn't work because there's no such field facebook_username in CommentsSchema...

So how can I include condition attached to fields from UsersSchema that will limit results from CommentsSchema?

Upvotes: 0

Views: 586

Answers (1)

Antonio Val
Antonio Val

Reputation: 3340

Since you have a reference to the corresponding user you could use populate.

Taking into account that try this:

Comments
.find({ 
    comment_date: { 
        $gte: startDate, 
        $lte: endDate 
    }
})
.populate('user_id')
.exec(function(err, comments) {
    if(err) {
        return res.send(err);
    }
    res.json(comments);
});

By the way, not related to the main question, but since you are not doing any change in the server I think a GET would be a better option.

I also abbreviated your query, $and is not necessary here.

EDIT

You can add filtering to populate, in your case:

.populate({
  path: 'user_id',
  match: { 
    facebook_username: fb_username 
  }
})

Upvotes: 1

Related Questions