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

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');

Related

Why is document.remove() not working in Mongoose, Node.js?

Problem: I try to delete a document from the database using document.remove() in the following codes, but it does not remove this document from database. I am confident remove() is called because the pre hook I set up for 'remove' is called.
// Delete - delete a player and update the team
router.delete("/:player_id", function(req, res) {
Player.findById(req.params.player_id, function(err, foundPlayer) {
if(err) {
console.log(err);
req.flash("error", "Player you want to delete is NOT FOUND!");
res.redirect("back");
return;
}
foundPlayer.remove(function(err, removedPlayer) {
if(!err) {
console.log(removedPlayer); // prints null
}
}); // <<<<<<<<<<<
res.redirect("back");
});
});
I then use model.findByIdAndRemove() in the following codes, and it worked.
// Delete - delete a player and update the team
router.delete("/:player_id", function(req, res) {
Player.findByIdAndRemove(req.params.player_id, function(err, foundPlayer) {
if(err) {
console.log(err);
req.flash("error", "Player you want to delete is NOT FOUND!");
res.redirect("back");
return;
}
res.redirect("back");
});
});
I have two Schemas:
var TeamSchema = new mongoose.Schema({
name: String,
players: [
{
type: mongoose.Schema.ObjectId,
ref: "Player"
}
],
});
var PlayerSchema = new mongoose.Schema({
name: String,
team: {
type: mongoose.Schema.Types.ObjectId,
ref: "Team"
}
});
Thank you so much in advance!
remove() has been deprecated,
try this
Player.deleteOne(req.params.player_id,function(err, removedPlayer) {
if(!err) {
console.log(removedPlayer); // prints null
}
}); // <<<<<<<<<<<
You have used the .remove() on the foundPlayer which was returned by the findByID . You should use the remove directly on the model from which you are trying to remove the document. For eg. The following would work -
Player.remove({_id:req.params.player_id},function(err, foundPlayer){
if(!err)
console.log(foundPlayer);
});
If the player with given _id has been found you will get something logged onto the console like this -
deleted
{ n: 1, ok: 1, deletedCount: 1 }
NOTE :
Trying to use remove() will probably give you an warning saying -
DeprecationWarning: collection.remove is deprecated. Use deleteOne, deleteMany, or bulkWrite instead.
So, you must use deleteOne or deleteMany instead according to your requirement. So your code should be like this -
Player.deleteOne({_id:req.params.player_id},function(err, foundPlayer){
if(!err)
console.log(foundPlayer);
});
You can also choose to use the following if you want to use the foundPlayerdoucment itself to be used in callback -
findOneAndDelete() / findByIdAndDelete() : Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if callback is passed, else a Query object is returned.
Hope this helps !

Mongodb, how to multiple request to aliment 1 object

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);
});

talking to PouchDB Basics

maybe it's an absolutely stupid question, but I have a Pouchdb Database that looks like this:
var fragDB = {
_id: new Date().toISOString(),
question: quest,
right: right,
wrong1: wrong1,
wrong2: wrong2,
wrong3: wrong3,
source1: source1,
source2: source2,
tags: tagarr
}
db.put(fragDB);
Now I want to retrieve the tags from the last document as an Array. I tried something like this, but this obviously didn't work.
var alltags = function(){
db.allDocs({include_docs: true, limit: 1, descending: true}, function(err, response){
if (err) {
console.log(err);
console.log("loading Standard Tags");
return ["..."];
}
if (response){
console.log(response.tags);
return response.tags;
}
});
};
What am I missing?
Not a dumb question – it just hard to grok, because PouchDB is asynchronous: http://pouchdb.com/guides/async-code.html
In your code, you have a function within a function, and it's the sub-function that's returning response.tags, not the parent function.
I suggest you read up on the link above, so you can learn how to write promisey async code like e.g.:
db.allDocs({
include_docs: true,
limit: 1,
descending: true
}).then(function (response) {
console.log(response.tags);
return response.tags;
}).catch(function (err) {
console.log(err);
console.log("loading Standard Tags");
return ["..."];
}).then(function (tags) {
// do something with the tags
});

How to refactor a "callback pyramid" into promise-based version

I'm currently struggeling to really understand how to refactor my code to use promises/the Q library.
Consider the following common basic example: I have a testcase that imports the same file twice into a mongodb and then checks whether the dataset name for the second import got some modifier at the end.
importDataSet('myFile.csv',function () {
importDataSet('myFile.csv',function () {
DataSet.find({title: 1}, function (err, result) {
result.length.should.be.equal(2);
result[0].title.should.startWith('myFile');
result[1].title.should.startWith('myFile');
result[0].title.should.not.be.equal(result[0].title);
done();
});
});
});
done();
});
(done() is the final callback):
So how would I do this using promises?
Preferably without changing the function signatures, (I followed the convention to have callbacks as the last parameter).
I am not sure why done() is called twice in your code, but without that, it may look similar to:
importDataSet('myFile.csv')
.then(function () {
return importDataSet('myFile.csv')
}).then(function () {
return DataSet.find({title: 1})
}).then(function (result) {
result.length.should.be.equal(2);
result[0].title.should.startWith('myFile');
result[1].title.should.startWith('myFile');
result[0].title.should.not.be.equal(result[0].title);
done();
});

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