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.
Related
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);
});
});
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'm trying to retrieve data from my mongolab DB using Node-mongodb-native
var findAll = function () {
var ddocs;
collection.find({}).each(function (arr, docs) {
ddocs = docs;
});
console.log(ddocs);
};
But it seems that when I log ddocs, it will give me undefined, but if I log docs it will show me the data.
Please help
How should I use this function ?
Thanks
Tzelon Machluf
You're basically trying to create a function that will return all of the documents in a collection? If so, the below should do work. However, I agree with #hgoebl and that you should work on your understanding of node as this is not likely the best way to accomplish what you're trying to do.
var ddocs;
var findAll = collection.find().toArray( function(err, docs) {
if(err)
throw err;
console.log('Collection returned');
return ddocs = docs;
});
setTimeout( function(err) {
if(err) throw err;
console.log(ddocs);
db.close();
}, 1000);
One thing in particular to note: collection.find is asynchronous, so the problem in your code (why it says ddocs is undefined) is that you're logging ddocs before the collection.find ever finished; thus, it's initialized, but no assigned any values. The Node convention is to nest callbacks so that everything happens in the right order and when it's ready.
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.