NodeJS array push is not working [duplicate] - node.js

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 7 years ago.
I am doing very simple requests to take some data from MongoDB and then send them to my views
router.get('/', isAuthenticated, function(req, res) {
Conversation.findAllConversation(req.user._id, function(err, data) {
if (err) return console.error(err); // handle this
var array = [];
data.forEach(function (element, index, array){
ConversationReply.findLastReply(element._id, function(err, replys) {
if(err) return cosole.log(err);
console.log(replys);
array.push(replys);
});
});
console.log(array);
res.render('messages/index', {
title : 'Messages',
conversations: data,
user: req.user,
lastReplys: array });
});
});
But all data from replys is not pushing to my array and then just sending empty. Console.log(replys) showing me all my replys correctly.

findLastReply is returning asynchronously, while the request function is proceeding synchronously. To fix this, I would do something like this:
router.get('/', isAuthenticated, function(req, res) {
Conversation.findAllConversation(req.user._id, function(err, data) {
if (err) return console.error(err); // handle this
var array = [];
data.forEach(function (element, index, array){
ConversationReply.findLastReply(element._id, function(err, replys) {
if(err) return cosole.log(err);
console.log(replys);
array.push(replys);
if (array.length === data.length) {
// we are done! :D
console.log(array);
res.render('messages/index', {
title : 'Messages',
conversations: data,
user: req.user,
lastReplys: array });
}
});
});
});
});
Even better is to use Promises, but this is not required.

Related

Editing Large Collection in MongoDB

I am trying to edit an entire collection in my MongoDB Database.
The collection is about 12k documents in size.
I was trying to edit the files from my angular controller
let promises = [];
array.forEach(each => {
promises.push(this.commonService.postObject('editObject', each));
});
forkJoin(promises).subscribe(data =>{})
My node function
module.exports.editObject = (model) =>{
return function (req, res, next) {
model.findOneAndUpdate({
'_id': req.body._id
}, req.body, {
upsert: true
}, function (err, doc) {
if (err) return res.send(500, {
error: err
});
return res.send(req.body);
});
};
}
But I get the error Message
ERR_INSUFFICIENT_RESOURCES
Is there a smarter way to do that?

Unable to find result on ejs template when i passed json array to ejs template

Pplease help how can i print the results of every user on ejs template.
router.get('/', function(req, res, next) {
var resultArray=[];
mongo.connect(url, function (err, db) {
assert.equal(err, null);
var cursor = db.collection('user-data').find();
cursor.forEach(function (err, data) {
assert(err, null);
resultArray.push(data);
},function () {
db.close();
res.render('user-details', { items: resultArray, title:'User Details' });
});
});
});
This code is used to send json array i am able to find the length of array but unable to print results.

NodeJS / Mongoose Filter JSON

I am building a JSON API with ExpressJS, NodeJS and Mongoose:
Input -> id:
app.get('/folder/:id', function (req, res){
return Cars.find({reference: req.params.id}, function (err, product) {
if (!err) {
console.log(product);
return res.send(product);
} else {
return console.log(err);
}
});
});
It shows well the JSON:
[{"_id":"B443U433","date":"2014-08-12","reference":"azerty","file":"087601.png","
....:.
{"_id":"HGF6789","date":"2013-09-11","reference":"azerty","file":"5678.pnf","
...
I just want to display the _id in the JSON, so it is good when I have lots of data.
How I can do that? Something like a filter?
You can chain calls to select and lean to retrieve just the fields you want from the docs you're querying:
app.get('/folder/:id', function (req, res){
return Cars.find({reference: req.params.id}).select('_id').lean().exec(
function (err, product) {
if (!err) {
console.log(product);
return res.send(product);
} else {
return console.log(err);
}
});
});
You would have to iterate over your "products" object to obtain the ids
Something like this:
(Disclaimer: I haven't tested this)
app.get('/folder/:id', function (req, res){
return Cars.find({reference: req.params.id}, function (err, product) {
if (!err) {
console.log(product);
var ids = new Array();
for(var i = 0; i < product.length; i++){
ids.push(product[i]._id);
}
return res.send(JSON.stringify(ids));
} else {
return console.log(err);
}
});
});
--Edit
Also, "products" may already be a JSON string. You may want to parse it before looping.
product = JSON.parse(product);
Other answers are true but I think it's better to limit data in mongoose like this :(it's same as mongo shell commands)
app.get('/folder/:id', function (req, res){
Cars.find({reference: req.params.id} ,{ _id : true } ,function (err, product) {
if (!err) {
console.log(product);
} else {
console.log(err);
}
});
});

Response from node app returns nothing, but should return array

I am testing a nodeJS server, built on the express framework.
When a request is sent to the server, the server should send back some data, in the form of an array. Instead, it is sending back ''.
The test that I am trying to pass is as follows:
it('should send postgres data to the server', function(done) {
request(app)
.post('/chart')
.send({min:"1",max:"100",arrayLength:"12"})
.expect(200, sqlData)
.end(function(err, res){
if(err) {
done(err);
} else {
done();
}
});
});
Note that sqlData is equal to what the sent response should be.
When the router receives a POST request it does the following:
router.post('/', function(req, res) {
res.send(randomSqlTableSelector(req.body.min,req.body.max,req.body.arrayLength));
});
I have checked that req.body.min, max and arrayLength are all the numbers that I would expect them to be.
Thus, the problem is likely in my function randomSqlTableSelector, which, for whatever reason, when called inside of the router, simple returns the empty quotes ''
The function is as follows:
function randomSqlTableSelector(min,max,arrayLength) {
var filledArray = [];
pg.connect(conString, function(err, client, done) {
if(err) {
return console.error('error fetching client from pool', err);
}
client.query('SELECT cell1 FROM random AS retrievedNumber;', function(err, result) {
var psqlData = result.rows;
for (i in psqlData) {
filledArray.push(psqlData[i]["cell1"])
}
return filledArray
});
});
}
You cannot treat functions that perform asynchronous, non-blocking tasks as synchronous and blocking. Try passing in a callback instead:
function randomSqlTableSelector(min, max, arrayLength, cb) {
pg.connect(conString, function(err, client, done) {
if (err)
return cb(err);
client.query('SELECT cell1 FROM random AS retrievedNumber;', function(err, result) {
if (err)
return cb(err);
var psqlData = result.rows,
filledArray = [],
i;
for (i in psqlData)
filledArray.push(psqlData[i]["cell1"])
cb(null, filledArray);
});
});
}
Then use it in your route like:
router.post('/', function(req, res) {
var min = req.body.min,
max = req.body.max,
len = req.body.arrayLength;
randomSqlTableSelector(min, max, len, function(err, array) {
if (err) {
console.log(err);
return res.send(500);
}
res.send(array);
});
});

ExpressJS mongodb multiple queries

I want to take data with two collections.
How to send this data in one response?
This is my code:
//RETURN SINGLE QUERYE
exports.findById = function(req, res) {
//Get Params
var querye_id =new BSON.ObjectID(req.params.id);
var querye;
//Get Single Querye
db.collection('queryes', function(err, collection) {
collection.findOne({'_id':querye_id}, function(err, item) {
querye=item;
});
});
//Get Questions and Answers
db.collection('questions', function(err, collection) {
collection.find().toArray(function(err, items) {
querye.questions=items;
});
});
//Send Response
res.send(querye);
};
I have varible querye as undefined. How to solve this?
var async = require('async');
function getQueries(id, callback) {
db.collection('queryes', function(err, collection) {
collection.findOne({'_id':id}, callback);
});
}
function getQuestions(callback) {
db.collection('questions', function(err, collection) {
collection.find().toArray(callback);
});
}
exports.findById = function(req, res) {
var querye_id =new BSON.ObjectID(req.params.id);
async.parallel({
querye: async.apply(getQueries, query_id),
questions: getQuestions
}, function (error, results) {
if (error) {
res.status(500).send(error);
return;
}
results.querye.questions = results.questions;
res.send(results.querye);
});
};
What you should probably do is use deferreds/promises to get the results in a waterfall manner then return the results when everything is completed.
I like to use the async library for node.
https://npmjs.org/package/async
What this lets you do is queue up all of your async functions then report back success/failure. At the very end you will get the results.
Assuming you already required the async module your code would look something like this.
exports.findById = function(req, res) {
//Get Params
var querye_id =new BSON.ObjectID(req.params.id);
async.waterfall([
function(callback){
//Get Single Querye
db.collection('queryes', function(err, collection) {
collection.findOne({'_id':querye_id}, function(err, item) {
callback(null, item);
});
});
},
function(arg, callback){
//Get Questions and Answers
db.collection('questions', function(err, collection) {
collection.find().toArray(function(err, items) {
arg.questions=items;
callback(null, arg);
});
});
}],function(err, results){
//Send Response
res.send(results);
});
};

Resources