Mongodb, how to multiple request to aliment 1 object - javascript

i'm creating a forum, and i want to get the number of message in one topic,
so in my method GetListTopic i get the list of topic, and after i want to know how many message there is in one topic so i request the table forum_message for every topic in my list=>
db.Forum_Topic.count({}, function (err, topicount) { //nombre de topic
db.Forum_Topic.find().skip(skipNumber).limit(nombreDeTopicParPage).sort({ dateLastMessage: -1 }, function (err, dbres) {
//dbres = liste de topic
for (var i in dbres)
{
db.Forum_Message.count({ idTopic: new mongojs.ObjectID(dbres[i]._id) }, function (err, Messagecount) {
dbres[i].TotalMessage = Messagecount;
});
}
res.send([dbres, topicount]);
});
});
my need is to add in every object of my list the total message => dbres[i].TotalMessage = Messagecount;
but that don't work dbres[i].TotalMessage is set correctly in the function callback but when i send object TotalMessage doesn't exist ....
someone can help me please ?

The problem is that you are using for loop within an async function. And that res.send() statement does not wait for the loop to complete. It executes before.
There is a solution by using this async library. There are also many options in this library, however, I think the async.each() is the one you can try.
Good luck.

i finally found the solution to foreach update with nodejs and mongodb,
i use async.js here : https://www.npmjs.com/package/async
and to delete a liste of mail
async.each(ListeIdMailToDelete, function (mailID, callback) {
db.userMessageMail.find({ _id: db.ObjectId(mailID) }, function (err, dbres) {
if (dbres.length > 0)
{
if (dbres[0].expediteur == newplayer.pseudo || dbres[0].destinataire == newplayer.pseudo) {
db.userMessageMail.remove({ _id: dbres[0]._id }, function () {
callback(err);
})
}
}
});
}, function (err) {
console.log(err);
});

Related

How do I put this code in a function? node.js + mongoose

I have this line of codes, and I will use it a lot in most of routes, but the think is, it is pretty redundant to write a lot of of the same codes . It's not the best practice. So How do i put it in a function? so that I could use it so many times?
// Lines of codes that will be used alot.
Wardrobe
.findOne({ owner: req.user._id})
.populate('items.item')
.exec(function(err, foundWardrobe) {
if (err) return next(err);
console.log(foundCart);
res.render('main/checkout', {
wardrobe: foundWardrobe
});
});
// Function to reduce repetitive codes above
function wardrobe() {
// What do I put in here? I tried so many codes but didnt work.
}
Parameterize the changable bits:
function wardrobe(ownerId, populate, render) {
Wardrobe
.findOne({ owner: ownerId})
.populate(populate)
.exec(function(err, foundWardrobe) {
if (err) return next(err);
console.log(foundCart);
res.render(render, {
wardrobe: foundWardrobe
});
});
}
Then call it:
wardrobe(req.user._id, 'items.item', 'main/checkout');

async.waterfall bind context

I am currently working on a web application with node.js and I can't figure a context problem with the library async.
Here is a example of code of my application :
notification.prototype.save = function (callback) {
async.parallel([
// Save the notification and associate it with the doodle
function _saveNotification (done) {
var query = 'INSERT INTO notification (notification_id, user_id, doodle_id, schedule_id) values (?, ?, ?, ?)';
notification.db.execute(query, [ this.notification_id, this.user_id, this.doodle_id, this.schedule_id ], { prepare : true }, function (err) {
return done(err);
});
console.log("SAVE NOTIFICATION");
console.log("doodle_id", this.doodle_id);
}.bind(this),
// Save notification for the users with the good profile configuration
function _saveNotificationForUsers (done) {
this.saveNotificationForUsers(done);
}.bind(this)
], function (err) {
return callback(err);
});
};
So in this code, I have to use the bind method to bind the context of my object ( this ) because otherwise async change it. I got it.
But what I don't understand is why the code of this.saveNotificationForUsers does not work the same way :
notification.prototype.saveNotificationForUsers = function (callback) {
console.log("SAVE NOTIFICATION FOR USERS");
console.log("doodle id : ", this.doodle_id);
async.waterfall([
// Get the users of the doodle
function _getDoodleUsers (finish) {
var query = 'SELECT user_id FROM users_by_doodle WHERE doodle_id = ?';
notification.db.execute(query, [ this.doodle_id ], { prepare : true }, function (err, result){
if (err || result.rows.length === 0) {
return finish(err);
}
console.log("GET DOODLE USERS");
console.log("doodle id : ", this.doodle_id);
return finish(err, result.rows);
});
}.bind(this)
], function (err) {
return callback(err);
});
};
When I call the previous code, the first console.log is able to show me the "this.doodle_id" variable, which means the function knows the "this" context.
But the functions inside the waterfall call does not, even if I bind 'this' to them.
I figured a way to make it works by creating a 'me' variable which is equal to 'this' juste before I call waterfall, and by binding the functions with the 'me' variable' and not this, but I would like to understand why I am forced to do this when I use async.waterfall and not when I use async.parallel.
I hope I was clear with the description of my problem, if someone can help me understand it will be a great pleasure !
The problem you’re seeing has got nothing to do with parallel or waterfall but rather how in the waterfall case, you’re referencing this in the callback to notification.db.execute, whereas in the parallel case, there is only a call to done in there. You could use bind again to bind that callback as well:
async.waterfall([
function _getDoodleUsers (finish) {
//…
notification.db.execute(query, [ this.doodle_id ], { prepare : true }, function (err, result){
//…
}.bind(this)); // <- this line
}.bind(this)
], function (err) {
//…
});

Parse Cloud Code: Delete All Objects After Query

Scenario
I have an app that allows users to create an account, but also allows the user's the ability to delete their account. Upon deletion of their account I have a Cloud Code function that will delete all of the "Post"s the user has made. The cloud code I am using is...
//Delete all User's posts
Parse.Cloud.define("deletePosts", function(request, response) {
var userID = request.params.userID;
var query = new Parse.Query(Parse.Post);
query.equalTo("postedByID", userID);
query.find().then(function (users) {
//What do I do HERE to delete the posts?
users.save().then(function(user) {
response.success(user);
}, function(error) {
response.error(error)
});
}, function (error) {
response.error(error);
});
});
Question
Once I have the query made for all of the user's posts, how do I then delete them? (see: //What do I do HERE?)
You could use
Parse.Object.destroyAll(users); // As per your code – what you call users here are actually posts
See: http://parseplatform.org/Parse-SDK-JS/api/classes/Parse.Object.html#methods_destroyAll
Also, consider using Parse.Cloud.afterDelete on Parse.User (if that is what you mean by "deleting account") to do cleanups such as these.
Oh, and just to be complete, you don't need the save() routine after destroyAll()
Updates in-line below below your "What do I do HERE..." comment:
NOTES:
You don't need to call the save() method, so I took that out.
This, of course, is merely a matter of personal preference, but you may want to choose a parameter name that makes a little more sense than "users", since you're really not querying users, but rather Posts (that just happen to be related to a user).
Parse.Cloud.define("deletePosts", function(request, response) {
var userID = request.params.userID;
var query = new Parse.Query(Parse.Post);
query.equalTo("postedByID", userID);
query.find().then(function (users) {
//What do I do HERE to delete the posts?
users.forEach(function(user) {
user.destroy({
success: function() {
// SUCCESS CODE HERE, IF YOU WANT
},
error: function() {
// ERROR CODE HERE, IF YOU WANT
}
});
});
}, function (error) {
response.error(error);
});
});

Handling async database in nodejs

I'm new in node js. I'm using sails js as framework. I'm trying to use nested database query.
Please check the added code.
My current mongo collection name is todostatus. Form it i grabbed the data . Then I tried to use a callback function to iterate the data and update each item inside the data from database. But I'm not getting all the data. Can anyone please give me lead?
Thanks in advance,
Nixon
TodoStatus.find({todo_id : req.params.todo_id}).done(function(errs, responsible){
if(errs){
}
else{
function grabUsersName(todoRes, callback){
async.forEach(todoRes, function (item, callback2){
User.findOne ({id : item.user_id}).done(function (errses, user) {
if(errses)
{
console.log(errses);
}
else
{
item['name'] = user.name;
}
});
}, function(eerr) {
callback(todoRes);
});
}
grabUsersName(responsible, function(resultsa){
console.log(resultsa);
return res.view({
responsible: resultsa
})
})
}
})
I found the solution.
The issue is in the function grabUserName(). I missed to use callback for the async.forEach. Check the functions code for more information
function grabUsersName(todoRes, callback){
async.forEach(todoRes, function (item, callback2){
User.findOne ({id : item.user_id}).done(function (errses, user) {
if(errses){
console.log(errses);
}
else{
item['name'] = user.name;
callback2();
}
})
}, function(eerr) {
callback(todoRes);
});
}

RangeError when trying to execute mongodb query with mongoose/mongodb-native

I have a problem which has already cost me a couple of days and I totally fail to understand it. I use node.js and have a mongodb with places indexed for their coordinates. I verified that the index works fine beforehand. For a set of coordinates, I want to find the nearest place. Here's how I tried to go about it:
var Places = require(./models/places.js),
coordFinder = require('./coordFinder.js');
...
function getCoords(userId, callback) {
coordFinder.getCoords(userId, function(err, coords) {
if (err) {
callback(err);
} else {
callback(null, coords);
}
}
}
function getNearestPlaces(coords, callback) {
async.forEachSeries(
coords,
function(coord, done) {
Places.findOne(
{ coordinates: { $near: [ coord.lat, coord.lon ] } },
function(err, place) {
// do something with place
done();
}
)
},
function(err) {
callback(err ? err : null);
}
);
}
...
async.waterfall(
[
...
getCoords,
getNearestPlaces,
...
],
function(err) {
...
}
}
The mongodb query consistently fails with the following error message for the first query:
RangeError: Maximum call stack size exceeded
When I change the query in getNearestPlaces to
... { $near: [ 10, 10 ] } ...
I as consistently get no error and the correct place. The same happens if I avoid the call to coordFinderin getCoords and change getCoords to
function getCoords(userId, callback) {
callback(
null,
[
// some coordinates
]
);
I know the error indicates a stack overflow (increasing the stack size didn't help) but I can't figure out how I could have caused one. Does anyone have a clue as to why this happens? Thanks in advance for your insights!
Edit: It got the same problem when using mongodb-native directly, by the way, so mongoose seems not to be the problem. One more clue - using the same query never gives me a problem when I don't call it from within a callback. Could that be a source of error?
I use
node.js 0.6.14
mongodb 2.2.2
node module async 0.1.22
node module mongodb 1.2.5
node module mongoose 2.5.7
Cheers,
Georg
The problem is most likely coming from the hidden recursion of async.forEachSeries. Try wrapping the Places.findOne call with setTimeout like this:
function getNearestPlaces(coords, callback) {
async.forEachSeries(
coords,
function(coord, done) {
setTimeout(function () {
Places.findOne(
{ coordinates: { $near: [ coord.lat, coord.lon ] } },
function(err, place) {
// do something with place
done();
}
);
}, 1);
},
function(err) {
callback(err ? err : null);
}
);
}
This puts the Places.findOne call outside of the call stack of async.forEachSeries.
mjhm pointed me in the right direction. Apparently, the Number instanced passed to the mongoose query caused the stack overflow. I'm not sure why, but creating a new Number object from the old one (as mjhm suggested) or converting the number into a primitive with valueOf() solved the problem.
If anyone has a clue as to how the original Number object caused the stack overflow, I'd very much appreciate any insights you might have to offer.

Categories

Resources