Amaury Medeiros
Amaury Medeiros

Reputation: 2233

Add extra fields dependent of other query to query result in mongodb, using mongojs

I need to make a MongoDB query and add an extra field to each one of my results. The field values depend of the result of another query.

I'm trying to call the nested query in my server.js code. It's not working because res.json(data) is called before data elements are modified. I suspect there's a way to do what I want using a nested query (or using something like forEach or aggregate) in my db.js code, but my lack of experience with JavaScript/Mongo didn't let me to find a good solution.

Any help would be appreciated.

server.js

app.get("/get_users_list", function(req, res) {
    db.getUsersByCity(req.query.city, function(err, data) {
        if (err) {
            res.send(err);
        } else {
            for(var i in data) {
                var rec = data[i];
                db.checkVisitation({'user_id': req.query.user_id, 'friend_id': rec.user_id},
                    function(inner_err, inner_data) {
                        if (inner_data) {
                            rec["visited"] = "true";
                        } else {
                            rec["visited"] = "false";
                        }            
                });
            }
            res.json(data);
        }
    });
});

db.js

 var checkVisitation = function(visitJSON, callback) {
    db.visitations.findOne(visitJSON, callback);
 }

var getUsersByCity = function(city, callback) {
    db.users.find({'city': city}).toArray(callback);
}

EDIT:

I was able to fix the problem by adding a check inside my inner callback:

if (i == data.length - 1) {
    res.json(data);
} 

Upvotes: 0

Views: 336

Answers (2)

Andrei Beziazychnyi
Andrei Beziazychnyi

Reputation: 2917

You need to call res.json only after you get all responses from db. Since requests are asynchronous you need to organize code to wait for them to finish. There are two widely adopted approaches to organize code with asynchronous calls:

  1. Use async.js https://github.com/caolan/async
  2. Use promises https://github.com/kriskowal/q

I recommend you to start with async since it is closer to current code

Upvotes: 2

Kev Price
Kev Price

Reputation: 809

You have res.json(data) inside your for loop, so it is going to send the data in the first increment of the for loop - not when the loop is finished.

You need a callback or check to make sure the for loop is finished before you do res.json(data);

also you should probably set data[i]["visited"] = "true" or false rather than setting rec, as rec is a separate variable that you are not returning

Upvotes: 0

Related Questions