Mongoose Model#save return value - node.js

I would like to get the whole document instead of the added item when I do a save().
var newTodo = Todos({
ID: req.body.ID,
RuleName: req.body.RuleName
});
newTodo.save(function (err, todos) {
if (err) throw err;
res.send(todos);
});

You cannot get it, unless you extend model method, or get it inside save
Simple version
newTodo.save(function (err, todos) {
if (err) throw err;
Todos.find(err, todos) {
if (err) throw err;
res.send(todos);
}
});
Version with custom method
// in schema definition
TodosSchema.methods.saveAndFind = function(cb) {
var self = this;
self.save(function(err) {
if(err) throw err;
return self.model('Todos').find({}, cb);
})
};
// in controller
var newTodo = Todos({
ID: req.body.ID,
RuleName: req.body.RuleName
});
newTodo.saveAndFind(function (err, todos) {
if (err) throw err;
res.send(todos);
});

Related

MongoDB: Conditionally delete DB entries depending on changes in linked file

E.g.: FileName = Lakshmikantha.html and Username also Lakshmikantha. If that Lakshmikantha.html file is modified then I want to delete that user from DB.
app.js
app.post('/home',urlencodedParser,function(req1,res1){
var filname = req1.body.username;
var str;
var originalfile;
var flag;
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("mydb");
dbo.collection("users").insert(req1.body, function(err, res) {
if (err) throw err;
console.log("user "+req1.body.username+ " inserted");
// db.close();
});
dbo.collection("users").find().toArray(function(err, result) {
if (err) throw err;
res1.render('home',{user:result});
// db.close();
});
watcher.on('change', function(path1) {
var filename = path.basename(path1);
originalfile = pathParse(filename).name;
str = originalfile.toString();
console.log(originalfile);
flag = true;
});
db.close();
});
if(flag){
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("mydb");
dbo.collection("users").remove({"username":str}, function(err, obj) {
if (err) throw err;
console.log("1 document deleted" + str);
});
db.close();
});
}
});
/*MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("mydb");
//Delete the "customers" collection:
dbo.collection("users").drop(function(err, delOK) {
if (err) throw err;
if (delOK) console.log("Collection deleted");
db.close();
});
});*/
Here I am inserting users to DB through loginpage and if particular filename with that username appears, I want to delete the entry from the DB.

Finish execution if first query returns a value Node.js Express.js mongoDB

Before starting, please mind that i have been searching this over 2+ hours, the answer will be simple i know but i couldnt get it to work . i am new to express node mongodb,
MongoClient.connect(url, function(err, db) {
if (err) {
res.status(err.status); // or use err.statusCode instead
res.send(err.message);
}
var usernameGiven = req.body.usernameGiven;
//Select the database
var dbo = db.db("notifellow");
//run the query
var query = { username: usernameGiven , friends: []};
dbo.collection("users").findOne({ username: usernameGiven}, function(err, result) {
if (err){
res.status(err.status); // or use err.statusCode instead
res.send(err.message);
console.log("Query Error Occured!");
}
else {
if (result) {
//Send the response
res.send("EXISTS");
//I WOULD LIKE TO EXIT IF THIS LINE EXECUTES
}
}
});
dbo.collection("users").insertOne(query, function(err, result) {
if (err){
res.status(err.status); // or use err.statusCode instead
res.send(err.message);
console.log("Query Error Occured!");
}
else {
if (result) {
//Send the response
res.send("CREATED 201");
} else {
res.send("Failed to insert");
}
}
});
db.close();
});
my goal is to check if an user doesnt exists with given username, i would like to insert that to the DB.
i would like to exit if my query finds an match and arrange such that insertOne wont execute. please enlighten me!!
Once you are not using the async/await syntax you will have to nest the calls to MongoDB, so they execute in series. You can also use a module like async to achieve this.
MongoClient.connect(url, function(err, db) {
if (err) {
res.status(err.status); // or use err.statusCode instead
res.send(err.message);
}
var usernameGiven = req.body.usernameGiven;
//Select the database
var dbo = db.db("notifellow");
//run the query
var query = { username: usernameGiven , friends: []};
dbo.collection("users").findOne({ username: usernameGiven}, function(err, result) {
if (err){
res.status(err.status); // or use err.statusCode instead
db.close();
console.log("Query Error Occured!");
return res.send(err.message);
}
if (result) {
db.close();
return res.send("EXISTS");
}
dbo.collection("users").insertOne(query, function(err, result) {
if (err){
res.status(err.status); // or use err.statusCode instead
db.close();
console.log("Query Error Occured!");
return res.send(err.message);
}
db.close();
if (result) {
return res.send("CREATED 201");
}
res.send("Failed to insert");
});
});
});
Try this
dbo.collection("users").findOne({ username: usernameGiven}, function(err, result) {
if (err){
//put the error logic
}
else {
if (result) {
//Send the response
return result;
}
else{
// if above if block fails it means that user does not exist
//put the insert logic
}
});

node.js For i in files render item

I want to repeat some items in my template (twig) on different places, where each repeated item responds to file names in different directories, so first I need an array with filenames.
I don't know how to affect outer scope from function. This will not work:
var files_list = {'json': [], 'js': []}
fs.readdir('./public/json', function(err, items) {
if (err) throw err;
files_list.json = items;
});
res.render('index', { js: files_list.js, jsons: files_list.json });
This works, but how to render it again to get something from another directory.
fs.readdir('./public/json', function(err, items) {
if (err) throw err;
res.render('index', { jsons: items });
});
This is a var that you does't have synchronously at hand; So you should treat it the asynchronous way:
Use a callback function:
var getFiles = function(dir, cb) {
fs.readdir(dir, function(err, files) {
if (err) cb(err, null);
cb(null, files);
});
};
Usage:
getFiles('./public/json', function(err, files) {
if (err) throw err;
res.render('index', { jsons: files });
});
Or a promise:
var getFiles = function(dir) {
return new Promise(function(resolve, reject) {
fs.readdir(dir, function(err, files) {
if (err) reject(err);
resolve(files);
});
});
};
Usage:
getFiles('./public/json')
.then(function(files) {
res.render('index', { jsons: files });
}, function(err) {
throw err;
});

Updating each element in MongoDB database in for loop

I have an array of userIDs (MongoDB Objectids)which I want to iterate through and for each one, find its user entry in my MongoDB database of users, and update it, say modify the user's age. Then only when every user has been updated, do I want to say res.send(200); in my Node.js Express app.
I started out with the following code which is just plain wrong because of the asynchronous calls to findById:
for (var i = 0; i < userIDs.length; i++) {
var userID = userIDs[i];
User.findById(userID, function (err, user) {
if (err) throw err;
// Update user object here
user.save(function (err, user) {
if (err) throw err;
res.send(200);
});
});
}
Any ideas how I can do this? Is there perhaps a synchronous version of findById? Or perhaps a way to map through the array and apply a function to each element?
Thanks!
I think you want the forEach method of npm's async module. It would look something like this:
async.forEach(userIDs, function(id, callback) {
User.findById(id, function(err, user){
if(err) throw err;
user.save(function(err, user){
if(err) throw err;
callback();
}
}, function(err){
if(err){
throw err;
} else {
res.send(200);
}
}
}
The best way is to use promises.
An example with Q#all:
var q = require('Q');
var promises = userIDs.map(function(userID){
var deferred = q.defer();
User.findById(userID, function (err, user) {
if (err) return deferred.reject(err);
// Update user object here
user.save(function (err, user) {
if (err) return deferred.reject(err);
deferred.resolve(user);
});
});
return deferred.promise;
});
q.all(promises)
.then(function(users){
res.json(users);
})
.fail(function(err){
res.send(500,err);
});

Rewrite callback function with async series

I had this function:
exports.profileImage = function(req, res) {
var id = req.params.user_id;
userProvider.get(id, function(err, user){
if (err) throw err;
userProvider.getImageById(user['image_id'], function(err, image) {
if (err) throw err;
userProvider.writeImageToDisk(image, function(err, path){
if (err) throw err;
res.sendfile(path);
});
});
});
};
I rewrite it using local variables:
exports.profileImage = function(req, res) {
var id = req.params.user_id;
var userTemp = undefined;
var imageTemp = undefined;
async.series([
userProvider.get(id, function(err, user){
if (err) throw err;
userTemp = user;
}),
userProvider.getImageById(userTemp['image_id'], function(err, image) {
if (err) throw err;
imageTemp = image;
}),
userProvider.writeImageToDisk(imageTemp, function(err, path){
if (err) throw err;
res.sendfile(path);
})
]);}
I have a parameters which userProvider.getImageById (user json object) needs , it comes from userProvider.get function, Which invoked before, I save it to local variable.
I chose async to skip callback hell but it is not working.
Error:
Cannot read property 'image_id' of undefined.
userTemp is undefined at the point where you try to look up its image_id. It will only become not undefined when the previous asynchronous function has been called.
Using async.waterfall, you should be able to simplify your code considerably to something like (the untested);
var id = req.params.user_id;
async.waterfall([
function(callback) {
userProvider.get(id, callback);
},
function(user, callback) {
userProvider.getImageById(user['image_id'], callback);
},
userProvider.writeImageToDisk,
res.sendfile
]);
That's not how async.series works.
Each function in the array has to have the following signature:
function(callback) { ...; callback(...); };
Once the code for each function is done, you need to call the callback function to signal to async that it should run the next step (docs).
So your code should look like this:
async.series([
function(callback) {
userProvider.get(id, function(err, user) {
if (err) throw err;
userTemp = user;
callback();
});
},
function(callback) {
userProvider.getImageById(userTemp['image_id'], function(err, image) {
if (err) throw err;
imageTemp = image;
callback();
});
},
function(callback) {
userProvider.writeImageToDisk(imageTemp, function(err, path){
if (err) throw err;
res.sendfile(path);
callback();
});
}
]);
Better yet, take a look at async.waterfall for a way of passing results from one async function to the next.

Resources