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.
Related
I am building a page which needs to retrieve and list data from several different Mongodb collections. I've been doing separate queries in the Express router function then bunging the results into an array which is passed to the page where the relevant data for each section are accessed. This has worked ok so far with up to three queries, but, if I add a fourth query I get an error.
The router function looks like this:
router.get('/thetest',function(req,res){
var finalResult = {};
var MongoClient = mongodb.MongoClient;
var url = 'mongodb://localhost:27017/myapp';
MongoClient.connect(url, function(err, db){
if(err){
console.log("Connection Error",err);
}else{
var collection = db.collection('cats');
collection.find({}).toArray(function(err,result){
if(err){
console.log("Error retrieving cats");
}else if (result.length){
finalResult.ctlist = result;
console.log("cats OK");
}
});
var collection = db.collection('mice');
collection.find({}).toArray(function(err,result){
if(err){
console.log("Error retrieving mice");
}else if (result.length){
finalResult.mclist = result;
console.log("mices OK");
}
});
var collection = db.collection('cheese');
collection.find({}).toArray(function(err,result){
if(err){
console.log("Error retrieving cheese");
}else if (result.length){
finalResult.chlist = result;
console.log("Cheese OK");
}else{
console.log('No Documents');
}
});
var collection = db.collection('mice');
collection.find({}).sort({tailLength:1}).limit(3).toArray(function(err,result){
if(err){
console.log("Error retrieving alert bookings");
}else if (result.length){
finalResult.mtlist = result;
console.log("Mouse tail length ok");
res.render('thetest',{
"thelist":finalResult
});
}
db.close();
});
}
});
});
(using dummy collection names)
So, there are four queries made to three different collections. The results are listed in a Jade template using an each loop.
If I comment out any one of the four queries and just run the other three it works fine: the results are listed on the page. If I uncomment and run all four queries then Node will choke and, obviously, nothing is listed on the page. None of the collections are above about half a dozen documents in size with a handful of fields in each.
I'm pretty new to all this and I understand that this may not be the best way to do what I am attempting.
Can anybody a) explain where I'm going wrong and/or b) suggest a better approach?
Thanks
I think the problem is due to your code.
Node.js is an asynchronous programming language, so all the operations works parallely.
In your code 'db.close();' close the database connection. For eg. if all the db operation works parallely and the 4th one (in your code) execute firstly then it close the database connection. So it is not a good programming style.
So you can use 'async' library for solving this.
https://github.com/caolan/async
Sample code :
async.parallel([
function(callback){
dbOperation1(query, callback);
},
function(callback){
dbOperation2(query2, callback);
},
function(callback){
dbOperation3(query3, callback);
},
function(callback){
dbOperation4(query4, callback);
}
],
function(err, results){
if (err) {
renderError(err);
} else {
renderHTML(results[0], results[1], results[2], results[4]);
}
});
If you comment all four condition then I am pretty sure that you are commenting res.render('thetest',{
"thelist":finalResult
});
Hence code is chocked. Because express API always wait for response and if you not provide response sentence, then for some time is going to wait and then crash out.
Solution : You must write your response statement out of condition.
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.
I am having a hard time trying to find the last inserted element into mongo. I am using an example code I found and trying to make the query and display the item but I am getting an error. I understand I am suppose to do something like this.
db.collectionName.findOne({}, {sort:{$natural:-1}})
But this is what I have so far and it's not working.
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:27017/exampleDb", function(err, db) {
if(err) { return console.dir(err); }
var collection = db.collection('test');
var doc1 = {'hello':'doc1'};
var doc2 = {'hello':'doc2'};
var lotsOfDocs = [{'hello':'doc3'}, {'hello':'doc4'}];
collection.insert(doc1);
collection.insert(doc2, {w:1}, function(err, result) {});
collection.insert(lotsOfDocs, {w:1}, function(err, result) {});
collection.find({}).toArray(function(err, docs) {
console.log(docs[0]);
});
db.close();
});
This is the error.
nodejs/node_modules/mongodb/lib/mongodb/connection/base.js:246
throw message;
^
TypeError: Cannot read property '0' of null
I checked to make sure the database is not empty so I am not sure why it's returning null.
I've found a possible solution(here) to your problem. It might be due to the fact that the database connection closes before the operations that you have issued finish.
You can fix it by including the db.close() call inside the find query.
collection.find({}).toArray(function(err, docs) {
console.log(docs[0]);
db.close();
});
i am new to nodejs,i wrote a function like this:
function getResult(){
var result='';
//do something asynchronous,like query datebase and assign result
db.query(sql,function(err,res){
if(err) throw err;
result=res;
})
return result;
}
i run it
getResult();
but i can't get result. it seems to be the function return before the asynchronous steps .
can i waiting for the asynchronous steps done,and then let the function return ?how?
thanks..
it's an easy issue, but it contains an important concept in node.js. let's look at this:
your code :
function getResult(){
var result='';
//do something asynchronous,like query datebase and assign result
db.query(sql,function(err,res){
if(err) throw err;
result=res;
})
return result;
}
it runs like this: firstly, do
db.query (sql)
then, it may do
return result
directly.
because when the query operation is done, it will do
function(err, res){ ...}
so, you may get the answer you want, may not.
how to fix this? you can use callback like this:
function getResult(callback){
db.query (sql, function(err, res){
if (err) throw err;
callback res;
});
}
getResult(function(result){ 'do something you like with result' });
may it will help you!
by using callbacks. This is one of the core concepts of javascript.
function getResult(callback){
var result='';
//do something asynchronous,like query datebase and assign result
db.query(sql,function(err,res){
if(err) throw err;
callback(res);
})
}
use this function with
getResult(function(res){
// do something
});