I am trying to get all consultation of a patient and if a patient has more than one consultation then i need to iterate through foreach/map, here is my implement of this but this is not working, please help
in below code when i am hitting the api then the response i am receiving is this:
No default engine was specified and no extension was provided
if i am running this code without foreach then it is working and i am getting doc length
router.post('/get/consultations', function(req, res){
console.log("consultation"+req.body.patient_id);
var dc = {};
consultation.find({"patient":req.body.patient_id}).forEach(function(doc){
console.log(doc.length);
//dc.push(doc);
});
res.json(dc);
});
According to Mongoose Doc http://mongoosejs.com/docs/queries.html
When a callback function:
is passed, the operation will be executed immediately with the results passed to the callback.
is not passed, an instance of Query is returned, which provides a special query builder interface.
since your statement
consultation.find({"patient":req.body.patient_id})
didn't pass callback function as an argument. This statement returns a Query object which you can execute by using .exec eg.
// .find returns a Query object
var query = Person.find({ 'name.last': 'Ghost' });
// execute the query at a later time
query.exec(function (err, person) {
if (err) return handleError(err);
console.log('%s %s is a %s.', person.name.first, person.name.last, person.occupation) // Space Ghost is a talk show host.
})
so your code should be either one of these way
// using exec
consultation.find({"patient":req.body.patient_id}).exec(function(docs){
docs.forEach(function(doc){
console.log(doc.length);
});
// using callback
consultation.find({"patient":req.body.patient_id}, function(err,docs){
docs.forEach(function(doc){
console.log(doc.length);
});
});
// using promise (mongoose 4+)
consultation.find({"patient":req.body.patient_id}).then( function(docs){
docs.forEach(function(doc){
console.log(doc.length);
});
});
Related
I query one collection (messages) with mongoose. The result is an array of documents. Each document contains an ID for a different collection (users). Now I want to query the users collection for each ID from the messages collection.
The idea is to update each message object with the information from the user collection before returning it to the front end.
I tried using async.each. For some reason the final function is never called even though I am making sure the callback() function is called after each iteration.
app.get('/getmsg', function(req, res){
messages.find({query})
.exec(function(err, ms){
if(err) throw err;
async.each(ms, function(m, callback){
users.findOne({_id : m.userId})
.lean()
.exec(function(err, user){
if(err) {
console.log('error' , err);
callback();
} else {
m.userName = user.name;
// everything is working up to here
callback();
}
}), function(err){
res.send(ms); // this is never returned!
}
});
});
});
Is there a better way of achieving this? I assume this must be a common issue.
Thanks!
You can't use res.send. Instead create a function to get notified about it. Something like this.
// 1st para in async.each() is the array of items
async.each(items,
// 2nd param is the function that each item is passed to
function(item, callback){
// Call an asynchronous function, often a save() to DB
item.someAsyncCall(function (){
// Async call is done, alert via callback
callback();
});
},
// 3rd param is the function to call when everything's done
function(err){
// All tasks are done now
doSomethingOnceAllAreDone();
}
);
Can someone explain to me why i can't save the booksCount variable into the users json object? Here's my code
for(var user in users){
Books.count({author: users[user]['id']}).exec(function(err, count){
users[user]['booksCount']=count;
});
}
return res.view('sellers', {data: users});
Where Users is the list of users from the table which is the direct result of a User.find() method. User is the model.
Now if i try to print the users[user]['booksCount'] inside the for loop, it works fine. But when it goes outside the for loop the variable vanishes into thin air. Console prints 'undefined' outside for loop.
Because Books.count is an API call and all the API call are async so In
for(var user in users){
// It Will call the Books.count and leave the callback Function without waiting for callback response.
Books.count({author: users[user]['id']}).exec(function(err, count){
users[user]['booksCount']=count;
});
}
//As callback result didn't came here but the controll came here
// So, users[user] will be undefined here
return res.view('sellers', {data: users});
Use promises:
async.forEachOf(users, function (value, user, callback) {
Books.count({author: users[user]['id']}).exec(function(err, count){
users[user]['booksCount']=count;
callback(err);
// callback function execute after getting the API result only
});
}, function (err) {
if (err) return res.serverError(err.message); // Or Error view
// You will find the data into the users[user]
return res.view('sellers', {data: users});
});
I am having the hardest time finding a solution to something that should be so simple.. I would like to find a document in a mongo database and store it in a variable that i can use anywhere in a node.js app..
The closest I think I have gotten is
var path = db.collection('paths').find().toArray()
where path is a collection holding one document, but then console.log(path[0]) returns undefined..
Try asynchronous way, something like this
var path;
db.collection('paths', function(err, collection) {
collection.find({}).toArray(function(err, results) {
path = results;
console.log(results);
});
});
NOTE
Never try to run IO operation synchronously in node.js because node.js is single threaded. If you do, you would block the whole application. The api provided by mongodb nodejs native is asynchronous, that means the result is expected in some point of time in future but not immediately. As soon as the result is available callback function is called and you get your result.
If you are coming from synchronous coding background, its a paradigm shift. You need to change your mind to think asynchronously.
Probably I'm late answering to this question. I've started working with nodejs and I'm using MongoDB for store all the data and I had the same problem finding a solution to keep the documents in a variable.
As you may know, the queries are async and in that way you can't assign the result in a variable, instead of doing that you have to use a function as a callback and return the value there.
Here's a sample code that I'm using in my project:
var verifyUserExists = function(db, callback, username) {
var collection = db.collection('users');
collection.findOne({ 'login': username }, function(err, doc) {
assert.equal(null, err);
callback(doc);
});
}
mongoClient.connect(mongoUrl, function(err, db) {
assert.equal(null, err);
console.log('Connected successfully to server');
verifyUserExists(db, function(userExists) {
console.log(userExists);
db.close();
}, username);
});
If you want to do other operations with the returned documents you have to do it in the callback, if you try to return the value in the callback function to a global variable you will get undefined because the code is executed async.
When I run collection.find() in MongoDB/Node/Express, I'd like to get a callback when it's finished. What's the correct syntax for this?
function (id,callback) {
var o_id = new BSON.ObjectID(id);
db.open(function(err,db){
db.collection('users',function(err,collection){
collection.find({'_id':o_id},function(err,results){ //What's the correct callback synatax here?
db.close();
callback(results);
}) //find
}) //collection
}); //open
}
That's the correct callback syntax, but what find provides to the callback is a Cursor, not an array of documents. So if you want your callback to provide results as an array of documents, call toArray on the cursor to return them:
collection.find({'_id':o_id}, function(err, cursor){
cursor.toArray(callback);
db.close();
});
Note that your function's callback still needs to provide an err parameter so that the caller knows whether the query worked or not.
2.x Driver Update
find now returns the cursor rather than providing it via a callback, so the typical usage can be simplified to:
collection.find({'_id': o_id}).toArray(function(err, results) {...});
Or in this case where a single document is expected, it's simpler to use findOne:
collection.findOne({'_id': o_id}, function(err, result) {...});
Based on JohnnyHK answer I simply wrapped my calls inside db.open() method and it worked. Thanks #JohnnyHK.
app.get('/answers', function (req, res){
db.open(function(err,db){ // <------everything wrapped inside this function
db.collection('answer', function(err, collection) {
collection.find().toArray(function(err, items) {
console.log(items);
res.send(items);
});
});
});
});
Hope it is helpful as an example.
When I run collection.find() in MongoDB/Node/Express, I'd like to get a callback when it's finished. What's the correct syntax for this?
function (id,callback) {
var o_id = new BSON.ObjectID(id);
db.open(function(err,db){
db.collection('users',function(err,collection){
collection.find({'_id':o_id},function(err,results){ //What's the correct callback synatax here?
db.close();
callback(results);
}) //find
}) //collection
}); //open
}
That's the correct callback syntax, but what find provides to the callback is a Cursor, not an array of documents. So if you want your callback to provide results as an array of documents, call toArray on the cursor to return them:
collection.find({'_id':o_id}, function(err, cursor){
cursor.toArray(callback);
db.close();
});
Note that your function's callback still needs to provide an err parameter so that the caller knows whether the query worked or not.
2.x Driver Update
find now returns the cursor rather than providing it via a callback, so the typical usage can be simplified to:
collection.find({'_id': o_id}).toArray(function(err, results) {...});
Or in this case where a single document is expected, it's simpler to use findOne:
collection.findOne({'_id': o_id}, function(err, result) {...});
Based on JohnnyHK answer I simply wrapped my calls inside db.open() method and it worked. Thanks #JohnnyHK.
app.get('/answers', function (req, res){
db.open(function(err,db){ // <------everything wrapped inside this function
db.collection('answer', function(err, collection) {
collection.find().toArray(function(err, items) {
console.log(items);
res.send(items);
});
});
});
});
Hope it is helpful as an example.