Express js use values from mongodb to outside of the query - node.js

I am new with express js and node js. I am wonder if its possible to do this or not.
1st thing I'm trying to get the count on 1 query.
2nd I query collection login. loop it and format and get the name values using ids.
I get undefined on count1 and I see it ommitted on the json response.
how do I pass the query returns outside of the query?
router.post('/logmein', function(req, res, next) {
var email = req.param('email');
var password = req.param('password');
var count1;
MongoClient.connect(MongoUrl, function(err, db) {
if (err) return;
db.collection('users').count({email: email,password: md5(password)}, function(err, count) {
count1 = count;
});
db.collection('login').find({email: email,password: md5(password)}).toArray(function(err, results){
console.log(results); // output all records
});
//use results
/*
foreach each results format with other info
var new_array;
*/
res.json({"success": true,"count":count1,new_array: new_array});
});
});

Async issues, you have to look more at it. Use the async module and then you will be able to fire the queries in parallel. Finally, you will have the results in the final callback. This snippet will fix your issue:
var async = require('async');
router.post('/logmein', function (req, res, next) {
var email = req.param('email');
var password = req.param('password');
var retResults;
var count1;
MongoClient.connect(MongoUrl, function (err, db) {
if (err) return;
async.parallel([
function(callback){
db.collection('users').count({ email: email, password: md5(password) }, function (err, count) {
return callback(err, count);
});
},
function(callback){
db.collection('login').find({ email: email, password: md5(password) }).toArray(function (err, results) {
return callback(err, results);
});
}
], function(err, results) {
if (err) {
// #todo: handle the error
}
count1 = results[0];
retResults = results[1];
//use results
/*
foreach each results format with other info
var new_array;
*/
res.json({ "success": true, "count": count1, new_array: new_array });
};
});
});

You need something like async.parallel to control the async flow of your nodejs application
async.parallel([
function(callback){ ... },
function(callback){ ... }
], function(err, results) {
// optional callback
};

Related

Mongodb.connect does not execute callback function

Im trying to connect to my Mongodb and insert some documents if they are not already in the db. It works fine with the first inserts but in the function existInDatabase it sometimes does not execute the callback function.
var MongoClient = require('mongodb').MongoClient;
var mongoData = require('./mongoData');
var exports = module.exports = {};
var dbName = 'checklist';
MongoClient.connect(mongoData.ConString, {
useNewUrlParser: true
}, function(err, db) {
if (err) throw err;
for (var key in mongoData.Customers) {
if (!existsInDatabase(mongoData.Customers[key], 'Customers')) {
db.db(dbName).collection('Customers').insertOne(mongoData.Customers[key], function(err, res) {
if (err) throw err;
console.log('1 document inserted');
db.close();
});
}
}
for (var key in mongoData.Categorys) {
if (!existsInDatabase(mongoData.Customers[key], 'Customers')) {
db.db(dbName).collection('Categorys').insertOne(mongoData.Categorys[key], function(err, res) {
if (err) throw err;
console.log('1 document inserted');
db.close();
});
}
}
});
function existsInDatabase(obj, collection) {
var result = false;
MongoClient.connect(mongoData.ConString, {
useNewUrlParser: true
}, function(err, db) {
db.db(dbName).collection(collection).find({}).forEach(function(doc) {
if (doc.id == obj.id) {
result = true;
}
}, function(err) {
console.log(err);
});
});
return result;
}
I have made a few changes to your code. It seems you are new to async programming, spend some time to understand the flow. Feel free for any further query. Here is your code.
// Welcome to aync programming
// Here no one waits for the slow processes
var MongoClient = require('mongodb').MongoClient;
var mongoData = require('./mongoData');
var exports = module.exports = {};
var dbName = 'checklist';
// Make the connection for once only
MongoClient.connect(mongoData.ConString, { useNewUrlParser: true },
function(err, db) {
if (err) throw err;
var myDB = db.db(dbName); // create DB for once
for (var key in mongoData.Customers) {
//make call to the function and wait for the response
existsInDatabase(mongoData.Customers[key], 'Customers', function(err, result) {
//once the response came excute the next step
if (result) {
myDB.collection('Customers').insertOne(mongoData.Customers[key], function(err, res) {
if (err) throw err;
console.log('1 document inserted');
});
}
});
}
for (var key in mongoData.Categorys) {
//make call to the function and wait for the response
existsInDatabase(mongoData.Customers[key], 'Customers', function(err, result) {
//once the response came excute the next step
if (result) {
myDB.collection('Categorys').insertOne(mongoData.Categorys[key], function(err, res) {
if (err) throw err;
console.log('1 document inserted');
});
}
});
}
// Both the for loop will work randomly without any order
function existsInDatabase(obj, collection, cb) {
var result = false;
myDB.collection(collection).findOne({ id: obj.id }, function(err, result)
{
if (err) {
//this cb will work only when db operation is complited
cb(err);
} else if (result) {
cb(null, true);
} else {
cb(null, false);
}
});
}
});
This code may result in some error. Feel free to ask more questions over it
db.db(dbName).collection(collection).find({}) returns a cursor per the docs. You are missing .toArray():
db.db(dbName).collection(collection).find({}).toArray()...

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.

Is it possible to show the whole updated record instead of the updated field only?

So basically, I am creating an inventory management app and want to show the updated record to the user in the sense not just the field that was updated but the whole document itself. My question is
*How do I show the whole updated record instead of the updated field to the user ? *
I am using postman to test this api. This is my code and those with comments are what I have tried.
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var url = 'mongodb://localhost:27017/myproject';
module.exports = {
/*getCollection : function(req, res){
var issueQty = req.body.issueQty;
var itemDescrip = req.body.itemDescrip;
MongoClient.connect(url,function(err,db){
assert.equal(null,err);
var doc = findMultiple(db,req,function() {
db.close();
});
});
res.send(doc)
}*/
postCollection : function(req, res){
var issueQty = req.body.issueQty;
var itemDescrip = req.body.itemDescrip;
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
updateRecord(db, req, function() {
db.close();
});
//findMultiple(db, req, function(){
//db.close();
//});
});
res.send('Record Found. Now updating this document...' + itemDescrip + '
Record Updated. This is the new record with updated issueQty '
+ issueQty )
}
}
var updateRecord = function(db, req, callback) {
db.collection('documents').updateMany(
{ 'Item Description': req.body.itemDescrip},
{
$set: { 'Issued QTY': req.body.issueQty }
}
,
function(err, results) {
console.log(results);
console.log('Done');
callback();
});
};
/*var findMultiple = function(db, req, callback){
var issueQty = req.body.issueQty;
var itemDescrip = req.body.itemDescrip;
var cursor = db.collection('documents').find({'Issued QTY': issueQty, 'Item
Description': itemDescrip});
cursor.each(function(err,doc){
assert.equal(err,null);
if(doc != err){
console.log('Successfully queried');
console.log(doc);
return doc;
} else {
callback();
}
});
};*/
I have tried putting another function findMultiple to get the data and show the updated record in the response but it did not work and have thought about linking my query api and the update api together but am not sure how to go about it. Any help is appreciated, thanks!
You need to:
Inside updateRecord(), call the callback with the results object of the update operation
Inside postCollection(), the callback passed to updateRecord() will have access to the results object
postCollection : function(req, res){
var issueQty = req.body.issueQty;
var itemDescrip = req.body.itemDescrip;
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
updateRecord(db, req, function(results) {
res.send('Document...') //Do what you want with results here
db.close();
});
});
var updateRecord = function(db, req, callback) {
db.collection('documents').updateMany(
{'Item Description': req.body.itemDescrip},
{$set: { 'Issued QTY': req.body.issueQty }},
function(err, results) {
console.log(results);
console.log('Done');
callback(results); //pass results to the callback
});
};

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