Search code examples
node.jsmongodbasynchronousfind

Call find query after saving a array of contacts in nodejs mongodb applicaiton


In the following post request, I have to save a list of contacts once save is completed find query has to be fired

router.route('/uploadContacts')
    .post(function(req,res){
        for(var i = 0; i < req.body.vishReqBody.Contacts.length; i++) {
            contactNumberList.push(req.body.vishReqBody.Contacts[i].PhNo)

        }
        
        //find and save the contact details

        ProfileDetails.findOne({ 'PhNo' : {$in:contactNumberList}} ,
                function(err, profileDetail) {
                    req.body.vishReqBody.Contacts.find(
                        function(contact){
                            if(profileDetail&&profileDetail.PhNo&&contact&&contact.PhNo){
                                if(profileDetail.PhNo==contact.PhNo){
                                    var contactsDetails = new contacts();
                                    contactsDetails.PhNo=contact.PhNo
                                    contactsDetails.RegStatus=profileDetail.Reg_Status
                                    contactsDetails.profileId=profileDetail.Profile_Id
                                    contactsDetails.PhoneBookName=contact.Name
                                    contactsDetails.updatedByProfileId=req.body.vishReqHeader.AppId
                                    contactsDetails.save(function(err,result){
                                        logger.info("contacts saved");
                                    })
                                }
                            }
                            else{
                                var contactsDetails = new contacts();
                                contactsDetails.PhNo=contact.PhNo
                                contactsDetails.RegStatus=0
                                contactsDetails.PhoneBookName=contact.Name
                                contactsDetails.updatedByProfileId=req.body.vishReqHeader.AppId
                                contactsDetails.save(function(err,result){
                                    logger.info("inside else");
                                    logger.info("contacts saved");
                                })
                            }



                        })



                });

        
        //once after save this part has to be fired to send the response
        contacts.aggregate(
            [
                {
                    $lookup:
                        {
                            from: "ProfileDetails",
                            localField: "PhNo",
                            foreignField: "PhNo",
                            as: "Profile_Details"
                        }
                },
                {$match:{
                    $and: [
                        {PhNo: {$in: contactNumberList}}
                    ]
                }}
            ],
            function (err, result) {

                if(result){
                    res.send({
                        "result": {
                            "vishResHeader": {
                                "ReqNo": req.body.vishReqHeader.reqNo,
                                "ProcStatus": 0,
                                "ErrCode": 0,
                                "ErrMsgUsr": ""
                            },
                            "vishResBody": {
                                "Contacts": result
                            },
                            "vishResTrailer": {
                                "Authentication": ""
                            }
                        }
                    })
                }
   

            })


    });

But before the save quire completes the query is fired and returns a incorrect response not sure how to wait until the save operation is completed and later to fire the find query

Note: find query has to be fired only after save

please suggest a way to accomplish it

Request body for reference

{
    "vishReqHeader": {
        "ClientId": "0",
        "AppId": "100",
        "ApiCode": "1007",
        "ReqNo": "123456789"
    },
    "vishReqBody": {
        "RegPhNo": "9880889660",
        "Cnt": "3",
        "Contacts": [{
                "PhNo": "7777777777",
                "Name": "Alex"
            },
            {
                "PhNo": "9999999999",
                "Name": "Cindy"
            },
            {
                "PhNo": "8888888888",
                "Name": "Rob"
            }
        ]

    },
    "vishReqTrailer": {
        "DeviceData": "lat=12.9677992|lng=77.596204|IMEI=1234567890|appVer=3.0.1|OS=ANDROID|SoftVer=6.0.1",
        "Authentication": "securitytoken"
    }
}

Solution

  • You should use q or async package. Which helps your nodejs code to run serially. I have implemented with q, I hope you can relate with this :

    var InsertUser = function(fname, lname, email, password){
    var deferred = q.defer();
    
    var user = new Users();
    user.email = email;
    user.password = password;
    user.emailVerified = false;
    user.fname = fname;
    user.lname = lname;
    user.createdDate = new Date();
    user.updatedDate = new Date();
    
    user.save(function(new_user_err, new_user){
        if(new_user_err){
            deferred.reject(new_user_err);
        }else{
            deferred.resolve(new_user);
        }
    });
    
    return deferred.promise;
    }
    

    And routes to call this function :

    router.post('/RegisterUser', function(req, res){
    var email = req.body.email;
    var fname = req.body.fname;
    var lname = req.body.lname;
    var password = req.body.password;
    
    InsertUser(fname, lname, email, password).then(function(user_data){
    
        console.log(user_data);
        console.log("User registered successfully");
        res.json({result : 1})
    
    }, function(user_error){
    
        console.log(user_error);
        res.json({ error : user_error });
    
    });
    
    });
    

    So you can do the same wit your code. Make a separate function for ProfileDetails.findOne and save() which returns a promise and then fire query contacts.aggregate()