Iterating on Cursor from MongoDB - javascript

I am trying to get all the documents in the collection, so I can do something based on them.
I am using the following code:
var test = pool.getDbCollection('Events');
test.find() //get them all
.each(function (error, doc) {
if (error) {
throw error;
} else {
//I am not getting here
//I am getting TypeError: Object 5 has no method 'each'
//And there are 5 Documents in the collection
}
});
}
And keep getting: Object 5 has no method 'each'
This function works just fine (same connection properties):
exports.getEventData = function (data) {
var deferred = Q.defer();
var eventCollection = pool.getDbCollection('Events');//TO DO Move this to config file
eventCollection.findOne({"id":data},
function (err, docs) {
if (!err) {
deferred.resolve(docs);
console.log('INFO(getEvents Method): Got the data !!!!')
} else {
deferred.reject('INFO(getEvents Method): Failed to get the data');
}
}
);
return deferred.promise;
};
It looks like each function is tried on the last object, but that last object is not in existance. at least it look to me that way. But I might be totally wrong.

doc will be null in the last iteration of the loop as a signal that the loop has completed.

Related

cursor.forEach is not a function Node.js

Here I am trying to use forEach method to iterate through each document of the cursor and pushing it into the result array but i am getting an error at
forEach
here is my code :
var fetch = function(callback) {
// mongoose.connect('mongodb://localhost/registration');
mongoose.connect('mongodb://localhost/questiondb');
var cursor = user.find();
cursor.forEach(function (doc,err) {
if(!err)
resultArray.push(doc);
else
{
callback(false);
}
},
function () {
callback(resultArray);
});
};
error is :
TypeError: cursor.forEach is not a function
Mongoose's Model.find returns a Query object, not a cursor. Furthermore, if you pass a callback to find, you'll get just the behavior you're trying to create with fetch, where an array of documents are provided to the callback.
var fetch = function(callback) {
// Don't connect here, connect once during startup
// mongoose.connect('mongodb://localhost/questiondb');
user.find((err, resultArray) => {
if (!err) {
callback(resultArray);
}
else {
callback(false);
}
});
};
you need to convert in array
User.find(function (err,userx){
if (err){
throw err;
}
else{
//add this code sentence
var user_arr =Object.keys(userx).map(
function(key){
return userx[key];
}
);
//now, use forEach sentence
user_arr.forEach(function(us){
console.log(us.name);
})
}
})
Because the cursor is not an array.forEach function must be used on an array.

How to get index of items return by limit & descending createAt

This is the first time I've used Parse, I'm loving it so far, reading and writing data is working.
I now want to do something seemingly simple, but in the context of Parse seems like a pain to implement and my google-fu is failing me.
When I find the items like this:
var query = new Parse.Query(CommentClass);
query.limit(2);
query.descending('createdAt');
query.find({
success: function(object) {
callback({
comments: object
});
},
error: function(object, error) {
console.log('there was an error');
}
});
I want to know what indexes of the returned items are in the total list. If my list has 5 items, this will return the last 2 created, but there's no way - without another request knowing the number of items in the list.
There is not an easy way to do it in Parse. One way is to keep a global index in a separate object. In every new comment you need to get this global index, increment it, and put it into the comment. But it can get messy in case of comment deletions. Here is an example assuming no comment deletion:
SequenceForComment.js
// A class called SequenceForComment. Only one row.
// Only one integer property called 'sequence'.
// You can create the row by using the Parse dashboard in the beginning.
var SequenceForComment = Parse.Object.extend("SequenceForComment");
function getSequenceForComment(callback) {
var query = new Parse.Query(SequenceForComment);
return query.first().then(function (object) {
// https://parse.com/docs/js/api/classes/Parse.Object.html#methods_increment
//Increment is atomic.
object.increment('sequence');
return object.save();
}).then(function (object) {
callback(object.get('sequence'));
}, function (error) {
console.log(error);
callback(undefined);
});
}
module.exports = {
getSequenceForComment: getSequenceForComment
};
main.js
var SequenceModule = require("cloud/SequenceForComment.js");
Parse.Cloud.beforeSave("Comment", function(request, response) {
var comment = request.object;
// First time this comment will be saved.
// https://parse.com/docs/js/api/classes/Parse.Object.html#methods_isNew
if (comment.isNew()) {
// Get a sequence/index for the new comment
SequenceModule.getSequenceForComment(function(sequence) {
if (sequence) {
comment.set("sequence", sequence);
response.success();
} else {
response.error('Could not get a sequence.');
}
});
} else { // Not a new save, already has an index
response.success();
}
});

mongo / monk - not firing promise.done?

I'm using mongo/monk to try and get promises to reduce some CB ugliness but it seems to be creating more unusual problems to debug ("now you have two problems").
based off:
https://gentlenode.com/journal/node-4-monk-cheatsheet/45
I have a little routine to clear a collection and insert some data,
however the on.complete or on.success isn't firing
QuizPlugin.collection.remove({}, function(err, doc) {
Clog.log("QP", "removed"); // get this
var raw = FileReader.readDataFile(jsonfile);
var that = this;
raw.records.map(item => {
var p = QuizPlugin.collection.insert(item.fields);
console.log("p.type", p.type);
p.on("success", function(doc) {
console.log("done", doc) // never
});
p.on("complete", function(doc) {
console.log("done", doc) // not this one either
});
p.on("error", function() {
console.log("error") // or this ever show up
});
// this method also doesn't emit anything
// QuizPlugin.collection.insert(item.fields, function(err, doc) {
// console.log("inserted")
// });
// Clog.log("inserted:", item.fields.question);
})
})
Is there some other reason the inner on("success") aren't firing?
the docs seem pretty clear, if spartan
https://github.com/Automattic/monk#promises

Node js - How to correctly use make async network calls within a module

So for part of a project I am working on I have created a module that uses the Facebook graph API to make calls and return JSON data. I can console.log() the data within the method out fine and it's all good.
But I can not return the values from the methods, so I tried to use the 'async' npm module. I have followed the examples on the website, but still am struggling to get everything working, spent all day on it so far and still things arn't looking any clearer.
So what I am asking is:
Firstly I need to call the method that sets the authentication_token for the fbgraph api before I can do anything else
Then I need to call each of the functions (in any order) and get the json result for each and add it to one big json result
Finally I need to get this one big json result back into my origional javascript page (even though it's currently in a module), how would I invoke it?
Here is a snippit of my original module (only works with console.log, can't return)
module.exports = {
/**
* Pass the access token to the fbgraph module
* and call other methods to populate
*/
setUp: function (access_token) {
graph.setAccessToken(access_token);
},
/**
* Fetches users basic info:
* Age, Gender, Hometown, Relationship status
*/
getBasicInfo: function(){
graph.get("/me/", function(err, res) {
var result = {
'age' : _calculateAge(res.birthday),
'gender' : res.gender,
'hometown' : res.hometown.name,
'relationship_status' : res.relationship_status
};
//console.log(result);
return result;
}, function(){ console.log("DONE");});
},
/**
* Creates a body of text as a string
* made up of all the users status updates
*/
getPosts: function(){
graph.get("/me/feed?limit="+PHOTO_LIMIT, function(err, res) {
var posts = "";
for(var i=0;i<res.data.length;i++){
var obj = res.data[i];
if(obj.message!=undefined) posts += obj.message+"\n";
}
//console.log(posts);
return {'posts':posts};
});
},
/**
* Fetches a single dimension string array of
* photos user is tagged in
*/
getPhotos: function(){
graph.get("/me/photos?limit="+PHOTO_LIMIT, function(err, res) {
var photos = [];
for(var i=0;i<res.data.length;i++){
var obj = res.data[i];
photos.push(obj.source); // .source is full size image, .picture is a thumbnail
}
return {'photos': photos};
});
}
}
The rest of this module continues in a similar way
I have tried using parralel async
module.exports = {
getFacebookInfo: function (access_token) {
results = {};
setUp(access_token);
async.parallel([
facebookDataRequests.getBasicInfo(),
facebookDataRequests.getPosts()
Any guidence on how I should structure this would be very much appreciated, thanks in advance
I'd recommend that you structure this differently. It's not necessary to make three calls to Facebook, because you can get the info in one call as well.
So, what I'd do:
Call the Facebook Graph API using field expansion
Format results
Return results
Also, I'd advise you to use a Promise library like Q
Something like this (untested!):
module.exports = {
getFacebookInfo: function (access_token) {
setUp(access_token);
function setUp(access_token) {
graph.setAccessToken(access_token);
}
function getFBInfo() {
var deferred = Q.deferred();
graph.get("/me?fields=id,name,birthday,gender,hometown,relationship_status,feed.limit(25),photos.limit(25)", function(err, res) {
if (err) deferred.reject(err);
deferred.resolve(res);
});
return deferred.promise
}
function handleResult(result) {
var deferred = Q.deferred();
result.posts = result.feed.data
delete result.feed.data;
result.photos = result.photos.data
delete result.photos.data;
deferred.resolve(result);
return deferred.promise
}
Q.fcall(getFBInfo)
.then(handleResult)
.then(function(result) {
return result;
})
.catch(function (error) {
// Handle any error from all above steps
})
.done();
}
}
In your main file:
var FB = require('./path/to/file/above');
var results = FB.getFacebookInfo('ACCESS_TOKEN_SDAIOFHIOSDHFOSO');

Node.js: Undefined return value after database query

I got a file newuser.js (node.js environment featuring a mongodb database managed via mongoose) containing the following code:
//newuser.js
//basically creates new user documents in the database and takes a GET parameter and an externally generated random code (see randomcode.js)
[...]
var randomCode = require ('randomcode');
var newTempUser = new tempUser({name: req.body.name, vericode: randomCode.randomveriCode(parameter)
});
newTempUser.save(function (err){
//some output
});
//randomcode.js
//creates a random sequence of characters (=vericode), checks if code already exists in DB and restarts function if so or returns generated code
exports.randomveriCode = function randomveriCode(parameter){
[...]
var TempUser = conn.model('TempUser', TempUserSchema);
TempUser.count({vericode: generatedcode}, function(err, counter){
if (counter=='0'){
return generatedcode;
}else{
randomveriCode(parameter);
}
});
};
Problem is, that newuser.js throws an error as variable vericode is 'undefined' (thus mongoose model validations fails). The error does not occur if I skip the database query and instantly return the generated code (which in fact has got a value as verified by several console.log instructions). It occurs to me that the db query takes to long and empty or null value returned before query is complete? I thought about introducing promises unless you got any other suggestions or hints what may cause this behaviour?
Kind regards
Igor
Since querying the database is a non-blocking operation, you cannot expect the function call to return the value from the database immediately. Try passing in a callback instead:
// newuser.js
var randomCode = require('randomcode');
randomCode.randomveriCode(parameter, function(err, code) {
if (err) throw err; // TODO: handle better
var newTempUser = new tempUser({name: req.body.name, vericode: code});
newTempUser.save(function (err){
//some output
});
});
// randomcode.js
exports.randomveriCode = function randomveriCode(parameter, cb) {
var TempUser = conn.model('TempUser', TempUserSchema);
TempUser.count({vericode: generatedcode}, function(err, counter) {
if (err) return cb(err);
if (counter == '0') {
cb(null, generatedcode);
} else {
randomveriCode(parameter, cb);
}
});
};
your randomveriCode function contains calls to an asynchronous function and therefore, your function really needs to provide a callback argument like this:
exports.randomveriCode = function randomveriCode(parameter, callback){
[...]
var TempUser = conn.model('TempUser', TempUserSchema);
TempUser.count({vericode: generatedcode}, function(err, counter){
if(err) return callback(err);
if (counter=='0'){
return callback(null, generatedcode);
}else{
randomveriCode(parameter, callback);
}
});
};
You'd then call it like so:
var randomCode = require ('randomcode');
randomCode(function(err, vericode){
if(err) throw err;
var newTempUser = new tempUser({name: req.body.name, vericode: vericode});
newTempUser.save(function(err,newUser){
//do something here
});
});
Btw - you could also use a synchronous function to create a GUID. See https://www.npmjs.org/package/node-uuid.

Categories

Resources