Express Mongoose Model.find() returns undefined - node.js

Hej, have a problem. Trying to send Express response with Mongo data in it.
This is code from my Express server
var Task = require('./modules/Task');
app.get('/get-all-tasks',function(req,res){
res.setHeader('Content-Type', 'application/json');
console.log(Task.getAllTasks()); // returns undefined
res.json({msg:"Hej, this is a test"}); // returns object
});
This is mongoose model in separate file
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/todo-app');
var TaskSchema = mongoose.Schema({
name: String,
assignee: String
},{ collection : 'task' });
var Task = module.exports = mongoose.model('Task', TaskSchema);
module.exports.createTask = function (newTask, callback) {
newTask.save(callback);
}
module.exports.getAllTasks = function(){
Task.find().lean().exec(function (err, docs) {
console.log(docs); // returns json
});
}
How can I properly send data from getAllTasks function?

That's looks correct, but your are forgetting about the Javascript's asynchronous behavior :). When you code this:
module.exports.getAllTasks = function(){
Task.find().lean().exec(function (err, docs) {
console.log(docs); // returns json
});
}
You can see the json response because you are using a console.log instruction INSIDE the callback (the anonymous function that you pass to .exec())
However, when you type:
app.get('/get-all-tasks',function(req,res){
res.setHeader('Content-Type', 'application/json');
console.log(Task.getAllTasks()); //<-- You won't see any data returned
res.json({msg:"Hej, this is a test"}); // returns object
});
Console.log will execute getAllTasks() function that doesn't return anything (undefined) because the thing that really returns the data that you want is INSIDE the callback...
So, to get it work, you will need something like this:
module.exports.getAllTasks = function(callback){ // we will pass a function :)
Task.find().lean().exec(function (err, docs) {
console.log(docs); // returns json
callback(docs); // <-- call the function passed as parameter
});
}
And the we can write:
app.get('/get-all-tasks',function(req,res){
res.setHeader('Content-Type', 'application/json');
Task.getAllTasks(function(docs) {console.log(docs)}); // now this will execute, and when the Task.find().lean().exec(function (err, docs){...} ends it will call the console.log instruction
res.json({msg:"Hej, this is a test"}); // this will be executed BEFORE getAllTasks() ends ;P (because getAllTasks() is asynchronous and will take time to complete)
});

I believe what you would need to do is return the docs in your getAllTasks function, but perhaps a better way to do it asynchronously using callbacks like so:
module.exports.getAllTasks = function(callback){
Task.find().lean().exec(function (err, docs) {
// If there is an error, return the error and no results
if(err) return callback(err, null)
// No error, return the docs
callback(null, docs)
});
}
And then inside your route you would do:
app.get('/get-all-tasks',function(req,res){
Task.getAllTasks(err, docs){
if(err) return res.json(error: err)
res.json(msg: docs);
}
});
I'm not sure if getAllTasks should be a mongoose static, in which case your model would look something like this:
TaskSchema.statics.getAllTasks = function (callback) {
return this.find().lean().exec(callback);
}

Related

Node.js async map over MongoDB queries

I'm having a problem with async Node.js module. In my Node.js app, I'm trying to get an array of JSON objects returned by a MongoDB request:
var fruits = ["Peach", "Banana", "Strawberry"];
var finalTab = [];
fruits.forEach(function(fruit) {
db.collection('mycollection').distinct("column1", {"column2":{$regex :fruit}}, (function(err, result) {
finalTab[fruit] = result;
console.log(result); // -> display the desired content
db.close();
if (err) throw err;
}));
});
console.log(finalTab); // -> []
At the moment, I'm at this point.
I'm trying to implement the async.map to iterate through Fruits collection.
https://caolan.github.io/async/docs.html#map
Can someone help? :)
Thanks by advance for help.
EDIT:
As I need all results returned by my db.collection functions, I'm trying to add these async commands to a queue, execute it and get a callback function.
You can try this:
async.map(fruits , function (fruit, callback) {
db.collection('mycollection').distinct("column1", {"column2":{$regex :fruit}}, (function(err, result) {
//here you are assigning value as array property
//finalTab[fruit] = result;
// but you need to push the value in array
finalTab.push(result);
console.log(result); // -> display the desired content
db.close();
if (err) throw err;
//callback once you have result
callback();
}));
}.bind(this), function () {
console.log(finalTab); // finally call
}, function (err, result) {
return Promise.reject(err);
});

Proper usage of a callback handler in Node

I am trying to get data that is being returned in a callback but my callback function (callbackFunc()) is not being executed, probably due to the way I am approaching this.If someone would point me in the right direction I would be grateful.
Thanks
var url = 'mongodb://localhost:27017/bac';
var term = 'usa';
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
findDocument(term.toUpperCase(),'country_code', db, function() {db.close();});
});
function callbackFunc(data){
console.log("inside callbackFunc()...");
console.log(data);
}
var findDocument = function(term, field, db, callbackFunc){
var collection = db.collection('bac');
collection.findOne({'country_code' : term}, function(err, document){
assert.equal(err,null);
console.log("Found this matching record for "+term);
console.log(document);
callbackFunc(document);
});
}
Let see your code:
findDocument(term.toUpperCase(),'country_code', db, function() {db.close();});
You pass wrong callback function, you pass function() {db.close();}.
i think you want pass:
function callbackFunc(data){
console.log("inside callbackFunc()...");
console.log(data);
}
so plese use:
findDocument(term.toUpperCase(),'country_code', db, callbackFunc);
The callback function been called is not the defined callbackFunc
function callbackFunc(data){ console.log("inside callbackFunc()..."); console.log(data); }
but the
function() {db.close();}
Because you are passing in the function arguments.

How to set a variable to a query? mongodb

How do I set a variable to a query? I am trying to use functions and callbacks in node.js to work through async, but I am not sure how to get a query to equal to a variable. What I am trying to do in this code is take a friend collection that belongs to a user and return the friends result(which I don't think I am doing correctly in the query insertAll) and then find the user's info for each of the query. And then return the results as a render. I am not sure how to call render either with this...
Here is my code:
exports.contactList = function(req, res) {
var insertFriend = function(data, callback) {
var friend = User.findById({_id: user.friendStatus.fuId}, function() {
callback(null, data);
}, friend);
};;
var insertAll = function(coll, callback) {
var queue = coll.slice(0),
friendX;
(function iterate(){
if(queue.length === 0) {
callback();
return;
}
friendX = queue.splice(0,1)[0];
insertFriend(friendX, function(err, friendX) {
if(err) {throw err;}
console.log(friendX + ' inserted');
process.nextTick(iterate);
});
})();
};
insertAll([Friend.findOne({userId: req.signedCookies.userid})], function(){
});
};
A Query object is returned if you do not pass a callback.
From 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 QueryBuilder
interface for you.

How to add an array of objects to parse.com db?

I'm developing an application and need to add many items at a time.
How can I do that with node.js?
This is the npm module for parse.com but there is no method like
insertAll("Foo", [objs...], ...)
I don't want to insert single object every time.
Write a convenience function that interfaces between your application and parse.com. You will have to write the iteration code once (or debug mine)
var async = require('async');
var parseApp = require('node-parse-api').Parse;
var APP_ID = "";
var MASTER_KEY = "";
var parseApp = new Parse(APP_ID, MASTER_KEY);
function insertAll(class, objs, callback){
// create an iterator function(obj,done) that will insert the object
// with an appropriate group and call done() upon completion.
var insertOne =
( function(class){
return function(obj, done){
parseApp.insert(class, obj, function (err, response) {
if(err){ return done(err); }
// maybe do other stuff here before calling done?
var res = JSON.parse(response);
if(!res.objectId){ return done('No object id') };
done(null, res.objectId);
});
};
} )(class);
// async.map calls insertOne with each obj in objs. the callback is executed
// once every iterator function has called back `done(null,data)` or any one
// has called back `done(err)`. use async.mapLimit if throttling is needed
async.map(objs, insertOne, function(err, mapOutput){
// complete
if(err){ return callback(err) };
// no errors
var objectIds = mapOutput;
callback(null, objectIds);
});
};
// Once you've written this and made the function accessible to your other code,
// you only need this outer interface.
insertAll('Foo', [{a:'b'}, {a:'d'}], function(err, ids){
if(err){
console.log('Error inserting all the Foos');
console.log(err);
} else {
console.log('Success!);
};
});

In node js how to get the result of the other module method in current module

ModuleTwo.js
exports.getNotificatiosById = function (notificationId) {
db.get(notificationId, function (err, doc) {
if(!err){
return true;
}
});
};
In modulelOne i need to get the result of the moduleTwo method.If moduleTwo method doesn't have the database query function means i can get that method result like below in moduleOne
var res=require('./lib/moduleTwo').getNotificatiosById;
If that db.get method has the synchronize method means i can do the query like
db.getSync(id);
Is there any other way to get the result of my moduleTwo method.Now i'm trying like below.Is it correct
moduleOne.js
var moduleTwo=require('./lib/moduleTwo');
moduleTwo.getNotificatiosById(id,function(err,res){
if(!err){
console.log('Result of the 2nd module is '+res);
}
});
You need to change getNotificatiosById to take a callback
exports.getNotificatiosById = function (notificationId,callback) {
db.get(notificationId, function (err, doc) {
if(!err){
callback(doc);
return true;
}
});
};
Then call it like
var moduleTwo=require('./lib/moduleTwo');
moduleTwo.getNotificatiosById(id,function(res){
console.log('Result of the 2nd module is '+res);
});

Resources