Return data from mongoDB nested queries - node.js

What is the method to return data from nested queries.
Im merging multiple function calls into one single module ,
I have the following code
retrieveStudentSessions: function(req, res, callback){
MongoClient.connect(config.mongoPath+config.dbName, function(err, db) {
if(err){
return callback(new Error("Unable to Connect to DB"));
}
var collection = db.collection(config.userList);
var sessionCollection = db.collection(config.session);
var templateCollection = db.collection(config.template);
var tempSession = {session:[], templates:[]};
//Obtain UserID
collection.find({'email' : req.user['_json'].email}).nextObject(function(err, doc) {
if(err){
return callback(new Error("Error finding user in DB"));
}
//Search Session collection for userID
sessionCollection.find({ $or : [{'studentsB' : doc['userid']},{'studentsA' : doc['userid']}]}).each(function(err, doc) {
if(err){
return callback(new Error("Error finding user in DB"));
}
//Update JSON
tempSession.session.push(doc);
//Query for Template Title using Template ID from Session Collection
templateCollection.find({'_id' : doc['templateId']}).nextObject(function(err, doc){
if(err){
return callback(new Error("Error finding user in DB"));
}
//Update JSON
tempSession.templates.push(doc);
});
});
return callback(null, tempSession);
});
});
}
Caller Function
dbCall.retrieveStudentSessions(req, res, function(err, result){
if(err){
console.log(err);
return;
}
console.log(result);
});
Above code returns error undefined is not a function when i try to return variable tempSession. The same works fine with single queries . Is there any specific method of return, when it comes to nested queries?

Related

Finish execution if first query returns a value Node.js Express.js mongoDB

Before starting, please mind that i have been searching this over 2+ hours, the answer will be simple i know but i couldnt get it to work . i am new to express node mongodb,
MongoClient.connect(url, function(err, db) {
if (err) {
res.status(err.status); // or use err.statusCode instead
res.send(err.message);
}
var usernameGiven = req.body.usernameGiven;
//Select the database
var dbo = db.db("notifellow");
//run the query
var query = { username: usernameGiven , friends: []};
dbo.collection("users").findOne({ username: usernameGiven}, function(err, result) {
if (err){
res.status(err.status); // or use err.statusCode instead
res.send(err.message);
console.log("Query Error Occured!");
}
else {
if (result) {
//Send the response
res.send("EXISTS");
//I WOULD LIKE TO EXIT IF THIS LINE EXECUTES
}
}
});
dbo.collection("users").insertOne(query, function(err, result) {
if (err){
res.status(err.status); // or use err.statusCode instead
res.send(err.message);
console.log("Query Error Occured!");
}
else {
if (result) {
//Send the response
res.send("CREATED 201");
} else {
res.send("Failed to insert");
}
}
});
db.close();
});
my goal is to check if an user doesnt exists with given username, i would like to insert that to the DB.
i would like to exit if my query finds an match and arrange such that insertOne wont execute. please enlighten me!!
Once you are not using the async/await syntax you will have to nest the calls to MongoDB, so they execute in series. You can also use a module like async to achieve this.
MongoClient.connect(url, function(err, db) {
if (err) {
res.status(err.status); // or use err.statusCode instead
res.send(err.message);
}
var usernameGiven = req.body.usernameGiven;
//Select the database
var dbo = db.db("notifellow");
//run the query
var query = { username: usernameGiven , friends: []};
dbo.collection("users").findOne({ username: usernameGiven}, function(err, result) {
if (err){
res.status(err.status); // or use err.statusCode instead
db.close();
console.log("Query Error Occured!");
return res.send(err.message);
}
if (result) {
db.close();
return res.send("EXISTS");
}
dbo.collection("users").insertOne(query, function(err, result) {
if (err){
res.status(err.status); // or use err.statusCode instead
db.close();
console.log("Query Error Occured!");
return res.send(err.message);
}
db.close();
if (result) {
return res.send("CREATED 201");
}
res.send("Failed to insert");
});
});
});
Try this
dbo.collection("users").findOne({ username: usernameGiven}, function(err, result) {
if (err){
//put the error logic
}
else {
if (result) {
//Send the response
return result;
}
else{
// if above if block fails it means that user does not exist
//put the insert logic
}
});

Setting a function callback fram an async request

Good Morning All,
I have been looking for an answer to this on the boards, but my noob brain just can't make sense of it.
i have this function in models/user.js
module.exports.getUserByUsername = function(username, callback){
var retUser = new User;
sql.connect(dbConfig, function(err) {
if (err) {
console.log(err);
callback();
}
// create Request object
var request = new sql.Request();
request.input('ip_username', sql.NVarChar, username)
// query to the database and get the records
request.query('select * from [portal_users] where username = #ip_username', function(err, recordset) {
if (err) {
console.log(err);
return;
} else {
var user = new User(recordset.recordset[0].username,recordset.recordset[0].password,recordset.recordset[0].email,recordset.recordset[0].name);
user.addID(recordset.recordset[0].id);
retUser = user;
}
callback();
// send records as a response
//res.send(recordset);
});
});
function callback() {
sql.close();
return retUser;
};
}
and this code in my routes/user.js
passport.use(new LocalStrategy(
function(username, password, done) {
User.getUserByUsername(username, function(err, user){
if(err) throw err;
if(!user){
return done(null, false, {message: 'Unknown User'});
}
User.comparePassword(password, user.password, function(err, isMatch){
if(err) throw err;
if(isMatch){
return done(null, user);
} else {
return done(null, false, {message: 'Invalid password'});
}
});
});
}));
I have been modifying an example from GITHUB that uses mongoDB for the DB connection, but I would like to use MS SQL. The function is successfully calling the database and returning the correct values. However I don't know how to initiate the callback so I can pass the retUser object back to the original function for processing and logging in.
I did for a moment try to do this by not using the callback and using a standard return type of function, however I quickly realised that given the async nature this wouldn't work.
any help here would be greatly appreciated.
Thanks
OK I managed to figure it out using this post:
Node.js npm mssql function returning undefined
my new code is:
module.exports.getUserByUsername = function(username, callback){
var connection = new sql.ConnectionPool(dbConfig, function(err) {
if (err) {
console.log(err);
callback(err);
return
}
// create Request object
var request = new sql.Request(connection);
request.input('ip_username', sql.NVarChar, username)
// query to the database and get the records
request.query('select * from [portal_users] where username = #ip_username', function(err, recordset) {
if (err) {
console.log(err);
callback(err,recordset);
return;
} else {
var user = new User(recordset.recordset[0].username,recordset.recordset[0].password.replace(/ /g,''),recordset.recordset[0].email,recordset.recordset[0].name);
user.addID(recordset.recordset[0].id);
callback(err,user);
}
sql.close();
// send records as a response
//res.send(recordset);
});
});
}

for loop giving an error while inserting document to collection

In node.js I am writing query to insert document to collection, but that query inserting only one document. Below the js code is,
app.js
router.post('/creatList', function(req,res){
console.log(req.body.email);
var emails = req.body.email;
if(req.body.wData.wishListType == 'Shared'){
var findUsers = function(db, callback) {
var cursor;
cursor = db.collection('users').find({email: { $in: emails }})
cursor.toArray(function(err, docs){
if(err){
callback(new Error("Some problem"));
} else {
callback(null,docs);
}
});
};
MongoClient.connect(config.database, function(err, db) {
assert.equal(null, err);
findUsers(db, function(err,docs) {
db.close();
console.log(docs);
var inserts_processing = 0;
for(var key in docs){
console.log(key);
var ids = docs[key]._id;
inserts_processing++;
console.log(ids);
var insertDocument = function(db, callback) {
db.collection('notifications').insertOne({
"userId" : ids,
},function(err, result) {
inserts_processing--;
assert.equal(err, null);
console.log("Inserted a document into the notifications collection.");
if(inserts_processing == 0){
db.close();
callback();
}
});
};
MongoClient.connect(config.database, function(err, db) {
assert.equal(null, err);
insertDocument(db, function() {
db.close();
});
});
}
});
});
} else {
console.log("other");
}
});
In the above code console.log contains two ids 570dec75cf30bf4c09679deb
56fe44836ce2226431f5388f but actually it inserting only last one.
According to your updated code I will try the following
router.post('/creatList', function(req,res){
console.log(req.body.email);
var emails = req.body.email;
if(req.body.wData.wishListType == 'Shared'){
// Open one connection to find users and insert documents
MongoClient.connect(config.database, function(err, db) {
assert.equal(null, err);
if(!err){
findUsers(db, function(err,docs) {
if(!err){
insertDocs(db, docs, function(){
db.close(); // Close connection
console.log("All documents have been inserted");
res.status(200).send("All is OK");
});
}
});
});
}
} else
console.log("other");
});
function insertDocs(db, docs, callback){
var inserts_processing = 0; // Will contain the number of inserts pending operation
for(var key in docs){
var ids = docs[key]._id;
inserts_processing++; // Before writing data, add one to processing inserts
db.collection('notifications').insertOne({
"userId" : ids,
}, function(err, result) {
inserts_processing--; // One insert have been finished, so remove one
assert.equal(err, null);
console.log("Document inserted into the notifications collection.");
// If all inserts have been finished, call back the function
if(inserts_processing == 0)
callback();
});
}
}
function findUsers(db, callback) {
var cursor;
cursor = db.collection('users').find({email: { $in: emails }})
cursor.toArray(function(err, docs){
if(err)
callback(new Error("Some problem"));
else
callback(null,docs);
});
};

Nodejs controller not working properly

router.get('/roomlist', function(req, res) {
var db = req.db;
var collection = db.get('roomlist');
collection.find(function(e,docs){
res.render('roomlist', {
"roomlist" : docs
});
});
});
The above controller is used to get list of rooms under a table "ROOMLIST". I need to get the details. I need to display all the roomname in the table ROOMLIST.
You should use find method of mongodb to get the documents from a collection. And then use cursor to iterate through the documents.
var getRoomlist = function(db, callback) {
var cursor =db.collection('roomlist').find( );
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
return callback(false, doc);
} else {
return callback(true, null);
}
});
};
Then you can use your route /roomlist, to call the function getRoomlist when it gets hit and render the doc.
router.get('/roomlist', function(req, res){
programLogic(function(err, doc){
if(err){
console.log(err);
}
return res.send(doc);
});
});
If you still don't get it, just clone this and run through it
var programLogic = function (cb){
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
getRoomlist(db, function(err, doc) {
if(err){
console.log(err);
}
return cb(false, doc);
});
});
}// programLogic ends
var getRoomlist = function(db, callback) {
var cursor =db.collection('roomlist').find( );
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
return callback(false, doc);
} else {
return callback(true, null);
}
});
};
router.get('/roomlist', function(req, res){
programLogic(function(err, doc){
if(err){
console.log(err);
}
return res.send(doc);
});
});
Which engine do you use for views rendering? Based on error message, property "roomname" has been interpreted as a partial, and cannot be found in views directory.

How to assign query results to an object

I am trying to transfer results data from query function to an object.
console.log(results) line returns 'undefined' result. What should I do?
module.exports = {
show: function(req, res) {
var results;
User.native(function(err, User) {
if(err) {
console.log("There is no exist a User by _id");
}
User.findOne({'_id' : req.param('id')},
function(err, user) {
results = user;
});
});
console.log(results);
return res.view({ stuff : results });
}
};
You have an async issue, the callback from findOne isn't necessarily executed in line with the rest of the code, so you get to the console.log(results) before results = user gets called. You'd want to change it to something like this:
show: function(req, res) {
var results;
User.native(function(err, User) {
if(err) {
console.log("There is no exist a User by _id");
}
User.findOne({'_id' : req.param('id')},
function(err, user) {
results = user;
console.log(results);
// Send response or make a callback here
});
});
}

Resources