Synchronize call in node.js - javascript

I am creating function in node.js from getting data from mongolab. It is just simple get method which return json
Here is my code:
app.get('/api/get_conversation_all_carer/:carer_id', function(req, res){
//Sender = user and receiver = carer
var values = [] ;
Conversation.aggregate([
{
$match: {
receiver_id: req.params.carer_id
}
},
{
$group: {
_id: "$sender_id",
}
}
],
function(err, result) {
if (err) {
console.log(err);
return;
}
for(var j = 0; j < result.length; j++) {
var object = {
"sender_id": result[j]._id,
"message": "",
"datetime": "",
"img": "",
"name":""
};
User.findOne({"_id": result[j]._id}, function(err, docs) {
object.img = docs.profile_pic;
object.name = docs.first_name;
});
Conversation.findOne({
$and: [
{
'receiver_id': req.body.carer_id
},
{
'sender_id': object.sender_id
}
]
},
{},
{
sort: {
'timer' : -1
}
},
function(err, docs) {
object.message = docs.message;
object.datetime = docs.timer;
values.push(object);
console.log("======= Inner =======");
}
);
}
console.log("====== OUT ======");
res = values;
}
);
});
Output:
====== OUT ======
====== Inner ======
I believe that Inner string should call first before Out, but here its happing reverse. I checked over other articals, but finding difficult to implement

Related

How to push inside nested array of object that have a precise value of a key in MongoDB?

I have one question about a problem that I'm not able to fix. I try to update push a string passed via Query in my mongoose collection.
My collection are like this:
{
"_id": {
"$oid": "6199288597e42bf84d017f9e"
},
"name": "Lisa",
"surname": "Bianchi",
"ID_school": "afbH598U3",
"classes": [
{
"class": "5A",
"activities": {
"in_progress": [],
"finisched": []
},
"_id": {
"$oid": "6199288597e42bf84d017f9f"
}
},
{
"class": "1A",
"activities": {
"in_progress": [],
"finisched": []
},
"_id": {
"$oid": "6199288597e42bf84d017fa0"
}
}
],
"email": "insegnante#a.com",
"__v": 0
}
and I try to push a string in in_progress array that match, for example, with class:"5A" using this way:
import db from "../models/index.js";
const Teacher = db.teacher
const updateActivity = (req, res) => {
const query = { _id: req.query.id};
const update = {$push:{'classes.$[group].activities.in_progress': req.query.data } };
const options = {arrayFilters: { 'group.class': req.query.class }};
Teacher.findOneAndUpdate(query, update, options).exec((err, data) => {
if (err) {
res.status(400).send({ message: err });
return;
} else {
res.status(200).send(data);
}
})
}
const API = {
updateActivity
}
export default API
The query works fine, but nothing was pushed. I tested whit Insomnia passing in the Query field
id = 6199288597e42bf84d017f9e;
class:'5A';
data:"pushed"
Any suggestion? Thanks!
try this way by passing classes.class in query and also change push to $push:{'classes.$.activities.in_progress': req.query.data }
const updateActivity = (req, res) => {
const query = { _id: req.query.id ,'classes.class': req.query.class};
const update = {$push:{'classes.$.activities.in_progress': req.query.data } };
Teacher.updateOne(query,update).exec((err, data) => {
if (err) {
res.status(400).send({ message: err });
return;
} else {
res.status(200).send(data);
}
})
}
There are two ways of doing this:
Option 1: arrayFilters - more flexible Docu
The option you are using.
You have a syntax error - arrayFilters should be an array of documents.
const updateActivity = (req, res) => {
const query = { _id: req.query.id };
const update = {
$push:{ 'classes.$[group].activities.in_progress': req.query.data }
};
// This MUST be an array of filter documents!
const options = { arrayFilters: [{ 'group.class': req.query.class }] };
Teacher
.findOneAndUpdate(query, update, options)
.exec((err, data) => {
if (err) {
res.status(400).send({ message: err });
return;
} else {
res.status(200).send(data);
}
});
}
Option 2: Via Query (as answered by #Saurabh Mistry)
Repeating his answer for completeness
By specifying a query that targets a particular element in an array within result documents.
const updateActivity = (req, res) => {
const query = {
_id: req.query.id,
'classes.class': req.query.data,
};
const update = {
$push:{ 'classes.$.activities.in_progress': req.query.data }
};
Teacher
.findOneAndUpdate(query, update, options)
.exec((err, data) => {
if (err) {
res.status(400).send({ message: err });
return;
} else {
res.status(200).send(data);
}
});
}

Res.redirect is not a function while using express in a nodejs webapp

I am trying to redirect to '/admin' route if the required data gets updated successfully but I am getting the error that res.redirect is not a function. I have tried writing return res.redirect also but it is also not working. Node experts, please help. Here I am just finding the student record on it's reg.no. basis and updating the record with its marks and redirecting to the admin page.
app.post('/admin/midterm/marks',(req,res)=>{
var m_written=[];
var m_practical=[];
var myjson=JSON.stringify(req.body);
course.subjects.map(sub=>{
if(!Array.isArray(req.body[`${sub}`]))
{
var p={subject:sub,mark:req.body[`${sub}`]}
m_written.push(p);
}
else{
var p={subject:sub,mark:req.body[`${sub}`][0]};
var q={subject:sub,mark:req.body[`${sub}`][1]};
m_written.push(p);
m_practical.push(q);
}
});
var first={
sem:course._id,
marks_sem:[{
term:ms,
m_written:m_written,
m_practical:m_practical
}]
}
if(!StudentRecord.total.length )
{
Student.updateOne({_id:check_Id},{total:first},function(err,res){
if(err)
{console.log("error");}
res.redirect('/admin');
});
}
else{
var flag=0;
StudentRecord.total.map(record=>{
if(record.sem==required_sem)
{
flag=1;
record.marks_sem.push(first.marks_sem);
Student.updateOne({_id:check_Id},{total:StudentRecord.total},function(err,res){
if(err)
{console.log("error");}
res.redirect('/admin');
});
}
});
if(flag==0)
{
StudentRecord.total.push(first);
Student.updateOne({_id:check_Id},{total:StudentRecord.total},function(err,res){
if(err)
{console.log("error");}
res.redirect('/admin');
});
}
}});
You override res in your callbacks. Name the second parameter in the callbacks result and everything will work fine.
app.post("/admin/midterm/marks", (req, res) => {
var m_written = [];
var m_practical = [];
var myjson = JSON.stringify(req.body);
course.subjects.map((sub) => {
if (!Array.isArray(req.body[`${sub}`])) {
var p = { subject: sub, mark: req.body[`${sub}`] };
m_written.push(p);
} else {
var p = { subject: sub, mark: req.body[`${sub}`][0] };
var q = { subject: sub, mark: req.body[`${sub}`][1] };
m_written.push(p);
m_practical.push(q);
}
});
var first = {
sem: course._id,
marks_sem: [
{
term: ms,
m_written: m_written,
m_practical: m_practical,
},
],
};
if (!StudentRecord.total.length) {
Student.updateOne({ _id: check_Id }, { total: first }, function (err, result) {
if (err) {
console.log("error");
}
res.redirect("/admin");
});
} else {
var flag = 0;
StudentRecord.total.map((record) => {
if (record.sem == required_sem) {
flag = 1;
record.marks_sem.push(first.marks_sem);
Student.updateOne(
{ _id: check_Id },
{ total: StudentRecord.total },
function (err, result) {
if (err) {
console.log("error");
}
res.redirect("/admin");
}
);
}
});
if (flag == 0) {
StudentRecord.total.push(first);
Student.updateOne(
{ _id: check_Id },
{ total: StudentRecord.total },
function (err, result) {
if (err) {
console.log("error");
}
res.redirect("/admin");
}
);
}
}
});

returning null when using value out of block

I am trying to query one collection, get IDs from that and with that I am querying another collection and send the response. No issue in that. My issue is I am using foreach, so I am trying to get the value out of block and send the response. But it's throwing null. I consoled the value inside the block, its giving the response but I couldn't access the value out of the block.
Code
getDetails = async (req, res) => {
let data: any[] = [];
await employee.find({
_id: new mongoose.Types.ObjectId(req.body.id)
}, (err, obj) => {
if (err) {
console.log("No Such Employee")
} else {
obj.forEach(element => {
employer.find({
user: new mongoose.Types.ObjectId(element.user)
}, (err, details) => {
if (err) {
console.log("No such employer")
} else {
for (var i = 0; i < detail.length; i++) {
let p_info = {
"id": detail._id,
"fname": details[i].fname "lname": details[i].lname "phone": details[i].phone,
"email": details[i].email,
}
data.push(p_info); // I can get value here
}
}
})
});
res.send(data); // Cannot get value here
}
});
}
return response only when all your asynchronous db calls are done. see below:
getDetails = async(req, res) => {
let data = [];
let employees;
try {
employees = await employee.find({
_id: new mongoose.Types.ObjectId(req.body.id)
});
} catch (err) {
console.log("No Such Employee");
}
let emp_len = employees.length;
employees.forEach((emp_obj, idx) => {
let details = await employer.find({
user: new mongoose.Types.ObjectId(emp_obj.user)
});
for (var i = 0; i < patient.length; i++) {
let p_info = {
"id": patient._id,
"fname": details[i].fname,
"lname": details[i].lname,
"phone": details[i].phone,
"email": details[i].email,
}
data.push(p_info); // I can get value here
}
if (emp_len == idx + 1) {
res.send(data); // Cannot get value here
}
});
}

Node.JS Mongoose findOne With for Loop

How can i use the for loop with findOne from mongoose in node.js, maybe have other logic that i can do the same thing?
data = { _id: '598b4e9abe74280be0b0cb1b' }
{ _id: '598b4ec1be74280be0b0cb1c' }
{ _id: '598b4fa8be74280be0b0cb1d' }
{ _id: '5992feccdad6db0c603b260d' }
{ _id: '5995e4ce0b38ba123cf06654' };
notification = new Array();
for (var i = 0; i < data.length; i++) {
Message.findOne({ from: data[i]._id, to:socket.handshake.session.passport.user }, function(err, message){
if (err){
console.log('error');
}
if(!message.length){
console.log('no message!!');
}else{
notification.push(message);
}
});
}
If you can transform your input data into an array you can do this:
var data = [ObjectId('598b4e9abe74280be0b0cb1b'),
ObjectId('598b4ec1be74280be0b0cb1c'),
ObjectId('598b4fa8be74280be0b0cb1d'),
ObjectId('5992feccdad6db0c603b260d'),
ObjectId('5995e4ce0b38ba123cf06654')];
Message.find({from: {$in: data}, to:socket.handshake.session.passport.user})

Want to send request in sync in node.js

I have a scenario that I want to fetch data from collection and insert into an array and then return that array.
router.route('/user/:_id/host/:_id/joineeList').get(function(req, res) {
var finalList = [];
Host.findOne({
_id : req.params._id,
}, function(err, host) {
if (err) {
res.send(err);
} else {
var count = host.joinees.length;
for (var i = 0; i < count; i++) {
console.log(host.joinees[i].userid);
var ID = host.joinees[i].userid;
var CODE = host.joinees[i].status_code;
User.findOne({
_id : host.joinees[i].userid
}, function(err1, user) {
if (err1) {
console.log(err1);
} else {
finalList.push({
"userId" : ID,
"name" : user.name,
"profilepic" : user.profilepic,
"status" : CODE
});
console.log(finalList);
// finalList[i].add = ("userId",ID);
// finalList[i].add = ("name",user.name);
// finalList[i].add = ("profilepic",user.profilepic);
// finalList[i].add = ("status",CODE);
}
});
}
}
});
});
Now, what is happening is that my array is returned null but data is inserted in finalList array also. Here is the console output:
[]
888888888888888888888888888888888888888888
[ { userId: '5485ae1159a751697e000003',
name: 'aaaa',
profilepic: 'https://graph.facebook.com/986962491123456/picture?type=large',
status: 0 } ]
------------------------------------------
[ { userId: '5485ae1159a751697e000003',
name: 'aaaa',
profilepic: 'https://graph.facebook.com/123456781319929/picture?type=large',
status: 0 },
{ userId: '5485ae1159a751697g7654003',
name: 'ssss',
profilepic: 'link',
status: 0 } ]
------------------------------------------
You could use this library - https://github.com/caolan/async#eachSeries. The method is eachSeries
Your code would look like this:
var async = require('async');
router.route('/user/:_id/host/:_id/joineeList').get(function (req, res) {
var finalList = [];
Host.findOne({
_id: req.params._id
}, function (err, host) {
if (err) {
res.send(err);
} else {
var count = host.joinees.length;
var limits = [];
for (var i = 0; i < count; i++) {
limits.push(i);
}
async.eachSeries(limits, function (i, callback) {
console.log(host.joinees[i].userid);
var ID = host.joinees[i].userid;
var CODE = host.joinees[i].status_code;
User.findOne({
_id: host.joinees[i].userid
}, function (err1, user) {
if (err1) {
console.log(err1);
} else {
finalList.push({
"userId": ID,
"name": user.name,
"profilepic": user.profilepic,
"status": CODE
});
callback();
}
});
}, function() {
console.log(finalList);
});
}
});
});
Let me know if it helped
You probably need the parallel method of the async library (or maybe map) check it out https://github.com/caolan/async#parallel
Thanks to #Vitaliy Zurian. I have used the following code, by using counter in the for loop
router.route('/user/:_id/host/:_id/joineeList').get(function (req, res) {
var finalList = [];
Host.findOne({
_id: req.params._id
}, function (err, host) {
if (err) {
res.send(err);
} else {
var count = host.joinees.length;
var limits = [];
for (var i = 0; i < count; i++) {
limits.push(i);
}
async.eachSeries(limits, function (i, callback) {
console.log(host.joinees[i].userid);
var ID = host.joinees[i].userid;
var CODE = host.joinees[i].status_code;
User.findOne({
_id: host.joinees[i].userid
}, function (err1, user) {
if (err1) {
console.log(err1);
} else {
finalList.push({
"userId": ID,
"name": user.name,
"profilepic": user.profilepic,
"status": CODE
});
callback();
}
});
}, function() {
console.log(finalList);
});
}
});
});

Categories