1

I have a code block like below. I could not find how to achieve that.
- I have rooms collection in mongodb and documents in this collection include user id array. Each room can have multiple users.
- So I want to find that usernames which are in the rooms that include my user Id.

DB collections:
Rooms {roomId:1, users:[99, 100]}, {roomId:2, users:[99, 101]}
Users {_id:99, name:"Alex"},{_id:100, name:"Harry"},{_id:101, name:"Tom"}

var userId = 99;
var arrUserIds = [];
var arrRooms = [];
var strUserNames = "";
db.collection("rooms").find({"users.userId":userId}).toArray(function(err, rooms) {

    for (var i=0; i<rooms.length; i++) {
        arrUserIds = [];

        for(var j=0; j<rooms[i].users.length; j++){
            arrUserIds.push(new BSON.ObjectID(rooms[i].users[j].userId));   
        }

        db.collection('users').find({"_id": {$in: arrUserIds}}).toArray(function(err, users) {
            strUserNames = users.map(function(elem){return elem.name;}).join(", ");
            arrRooms.push({_id:rooms[i].roomId, name:strUserNames });
        });

    }

    res.json({rooms:arrRooms});
});

I want to have a result like that:
arrRooms: [ { _id:1:, name:"Alex, Harry" }, { _id:2:, name:"Alex, Tom" } ]

Thanks

1 Answer 1

1

You're returning res.json before the second .find callback executes, so it will be empty. You need to restructure to wait for all the async callbacks before responding, like so:

var userId = 99;
var arrRooms = [];
var strUserNames = "";

db.collection("rooms").find({"users.userId":userId}).toArray(function(err, rooms) {

    var completed = 0;
    var complete = function() {
        completed++;
        if (completed === rooms.length - 1) {
            res.json({rooms:arrRooms});
        }
    }


    for (var i=0; i<rooms.length; i++) {
        var arrUserIds = [];
        var roomId = rooms[i].roomId;

        for(var j=0; j<rooms[i].users.length; j++){
            arrUserIds.push(new BSON.ObjectID(rooms[i].users[j].userId));   
        }

        db.collection('users').find({"_id": {$in: arrUserIds}}).toArray(function(err, users) {
            strUserNames = users.map(function(elem){return elem.name;}).join(", ");
            arrRooms.push({_id:roomId, name:strUserNames });

            complete();
        });
    }

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

7 Comments

I want to have a result like that: arrRooms: [{_id:1:, name:"Alex, Harry" },{_id:2:, name:"Alex, Tom" }] But your answer does not give me this result. I need to run second .find callback synchronously.
Ah, I see - I'll have another go.
@barisusanmaz Updated - does that cover it?
No, I am sorry it does not work. That gives me only last room information in 3 rooms.
@barisusanmaz one last try, I've just updated the answer; resetting the arrUserIds array inside the for loop.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.