Mongodb findone method does not work - node.js

function updateMongo(url, cached) {
console.log("Update mongo called");
MongoClient.connect('mongodb://127.0.0.1:27017/dbnerds', function(err, db) {
if(err) {
return console.log(err);
}
var cache = db.collection('cache');
cache.insert({url: url, image: null}, {safe: false}, null);
cache.findOne({ url: url }, function(err, result) {
console.log(result);
});
db.close();
});
};
As you can see from my code, that I insert url into mongodb, but when I do findOne operation, it seems it does not work. The console did not print out any result. What is wrong with here?

The problem is because there is no guarantee that the call to .insert() has finished when the call to .findOne() is executed.
Try using the following approach instead:
function updateMongo(url, cached) {
console.log("Update mongo called");
MongoClient.connect('mongodb://127.0.0.1:27017/dbnerds', function(err, db) {
if(err) {
return console.log(err);
}
var cache = db.collection('cache');
cache.insert({url: url, image: null}, {safe: false}, function(err, n) {
// Make the call to findOne until insert has finished
cache.findOne({ url: url }, function(err, result) {
console.log(result);
// close the DB after you are done
db.close();
});
});
});
};
Notice how I moved the call to findOne() to be the callback function executed after the insert has finished.

Related

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

Execute three operations in Mongodb or cancel if just one fails

I need to store one record in three different collections at the same time, but I need that if just one of this operations fails (for any kind of reasons) the entire procedure will be canceled. In a few words, I need to be sure that this record is stored correctly in each all the three collections: I need to avoid the situation where the record is stored in just two (or one) collections.
This is my actual code:
var insertOne = function(data) {
req.app.locals.db.collection('document_1').findOneAndUpdate({'id': data.id}, {$set: {'element': 'data.element}}, {returnOriginal: false}, function(err, result) {
if (err) {
console.log('error 1');
return;
}
if(result) insertTwo(data);
});
}
var insertTwo = function(data) {
req.app.locals.db.collection('document_2').findOneAndUpdate({'id': data.id}, {$set: {'element': 'data.element}}, {returnOriginal: false}, function(err, result) {
if (err) {
console.log('error 2');
return;
}
if(result) insertThree(data);
});
}
var insertThree = function(data) {
req.app.locals.db.collection('document_2').findOneAndUpdate({'id': data.id}, {$set: {'element': 'data.element}}, {returnOriginal: false}, function(err, result) {
if (err) {
console.log('error 3');
return;
}
if(result) console.log('success!');
});
}
insertOne(mydata);
Thanks.

Nodejs Angularjs Mongoose Query inside async map

From the codes below, I can add to my database. However, when I am trying to mongoose-find to look for the database, I am not getting any value. can anybody help? I want to res.json the result.
app.post('/api/infosave', function(req,res){
async.series([function (cb){
dbinfo.remove({}, function(err,result){
if (err) throw err;
cb(null);
});
}, function (cb){
var bookNum = [];
for (var i = 0; i < req.body.numBooks; i++) {
bookNum.push(i+1)
}
async.map(bookNum, function(num, cb) {
dbinfo.create({
numBooks: num,
done: false
}, cb);
}, cb);
}, function (cb){
dbinfo.find({},function(err,result){
if (err)
res.send(err);
res.json(result);
console.log(result);
cb(null);
});
}], function(error, results) {
});
});
As I said in my comment: you're calling res.json() inside one of the series function, and that won't work. What you should do is pass the result of dbinfo.find() to the local callback:
dbinfo.find({},function(err,result){
if (err)
cb(err);
cb(null, result);
});
, and in the async.series callback, call res.json():
...
}], function(error, results) {
if (error) return res.json({ error: error });
return res.json(results[2]); // the result you want should be third element of results
});

Avoid extra query with Mongo and Express in PUT

I'm updating a record in Mongo with Mongoose/Express:
app.put('/loggedIn/:id', function(req, res) {
if (req.user._id == req.params.id) {
User.update({
_id: req.user._id
}, {
$set: {
interests: req.body.interests
}
}, function(err, num) {
if (err) return err;
User.findById(req.user._id, '_id username interests', function(err, user) {
if (err) return;
res.json(user);
});
});
} else {
console.log('fail');
}
});
How can I avoid doing the second query in the callback of the update(), seems a lot just to return the newly updated document.
If you're always updating only one document you can use findByIdAndUpdate (or findOneAndUpdate), which updates the document if found and returns it to the callback:
app.put('/loggedIn/:id', function(req, res) {
if (req.user._id == req.params.id) {
User.findByIdAndUpdate(req.user._id, {
$set: {
interests: req.body.interests
}
}, function(err, user) {
if (err) return;
res.json(user);
});
} else {
console.log('fail');
}
});
I think you can get the raw Mongo response as the 3rd update callback argument. Check if this contains what you want. Otherwise, try passing the option { raw: true }.
See http://mongodb.github.io/node-mongodb-native/markdown-docs/insert.html
You could use findByIdAndUpdate instead of a separate find and update.
I also sometimes do User.Find() and then inside the success callback Doc.save(). That lets you do more complex things between if it's not just a straight update from the request.

apply update options without save for pre-validation - mongoosejs

In any webapp i press a plus button and a value will be increased.
When i hit the button fast the validation does not work, cause the validations does not prevent (excepted behavior, the value is not out of the validations range). But the value will be setted down further, cause the rest of the reqeust will be submitted.
Important: the update options are dynamically (for instance $inc or $set).
Current Code
module.model.update({ _id: id }, options /* are dynamic */, { safe: true }, function (err, updatedDocument) {
if (err) return respond(400, err);
module.model.findOne({ _id: id }, function (err, foundDocument) {
if (err) return respond(400, err);
foundDocument.validate(function (err) {
if (err) return respond(400, err);
return respond(200, foundDocument); // callback method
});
});
});
First guess to prevent the problem
module.model.findOne({ _id: id }, function (err, foundDocument) {
foundDocument.set(options);
foundDocument.validate(function (err) {
if (err) return respond(400, err);
foundDocument.save(function (err, savedDocument) {
if (err) return respond(400, err);
return respond(200, doc);
});
});
});
...then the save just will preformed when the validation is valid.
But there is a porblem: The set method does not support $inc or other pseudo setters, or does it?
I saw the possibility to use the constructor of the update function (Show Code), but i don't know how to use it: this.constructor.update.apply(this.constructor, args);
Do you have any good practise for this problem ?
The solution was to create a customized version for $inc.
What i've done is to replace the set method of mongoosejs.
This is now extendable, but a quiet custom way to validate before an update. When someone have another solution. Post it please.
module.model.findOne({ _id: id }, function (err, foundDocument) {
for(var optionsProp in options) {
if(optionsProp === '$inc') {
for(var incProp in options[optionsProp]) {
foundDocument[incProp] += options[optionsProp][incProp];
}
}
}
foundDocument.validate(function (err) {
if (err) return respond(400, err);
foundDocument.save(function (err, savedDocument) {
if (err) return respond(400, err);
return respond(200, savedDocument);
});
});
});

Resources