Nodejs, MongoDB asynchronous callback problem - node.js

I'm the beginner of nodejs and MongoDB.I tried to design RESTAPI but there was a problem.
Here is my router code.
app.post('/fcm',function(req,res){
var beaconid = req.body.beacon_id;
var my_token_id = req.body.user_id;
User.find({beacon_id: beaconid}, function(err, output){
if(err) return res.status(500).json({error: err});
if(!output) return res.status(404).json({error: 'user not found in User collections.'});
console.log("output user id :"+output.user_id + " beacon: " +output.beacon_id );
target_token_id = output.user_id;
res.json(output);
});
});
And this is user schema.
var userSchema = new Schema({
user_id: String,
beacon_id: String
});
The result of above function in the console is:
output user id: undefined , beacon: undefined.
But json from res function is printed properly.
This codes look like very simple but I don't know what is the problem.
Please somebody help me.

By using find, you are expecting 1 document or more. This means that the method <Model>.find() should logically return an array. You can make sure that is what happens by logging the output just after the query to make sure it is an array of documents.
To solve your problem, you can either access the document at index 0 of the array:
User.find({beacon_id: beaconid}, function(err, output){
if(err) return res.status(500).json({error: err});
if(!output) return res.status(404).json({error: 'user not found in User collections.'});
console.log("output user id :"+output[0].user_id + " beacon: " +output[0].beacon_id );
target_token_id = output[0].user_id;
res.json(output);
});
Or use findOne() instead, that returns only one document.
User.findOne({beacon_id: beaconid}, function(err, output){
if(err) return res.status(500).json({error: err});
if(!output) return res.status(404).json({error: 'user not found in User collections.'});
console.log("output user id :"+output.user_id + " beacon: " +output.beacon_id );
target_token_id = output.user_id;
res.json(output);
});

Related

mongoose findOne data does not exit not working

user_id 2 does not exist in mongodb but console log does not print 'does not exist'
var query = PostData.findOne({ 'user_id': '2'});
query.exec(function (err, doc) {
if(doc) {
console.log('ok');
} else {
console.log('does not exist');
}
});
Without mongoose it works:
connection.db.collection("PostData", function(err, collection){
collection.find({ 'user_id': '2'}).toArray(function(err, data){
console.log(data); // it will print your collection data
})
});
prints []
No matter an object exists or not , MongoDB is going to return an array anyway. If the object exists, they array will be filled with it otherwise it's just an empty array. So if you want to check if the user exists or not you must check for doc.length , if it's 0 then it means the user doesn't exist.

How to retrieve document in mongoose

I have multiple document in collection having a long string in each document, I want to retrieve one document at time, I dont have anything in document except long string, how can I retrieve that?
I inserted all document in collection using insertMany(), here is my code and output when I retrieved all document
var schema = new mongoose.Schema({
question : String,
id: Number
})
var quizz = mongoose.model('Quiz', schema );
var firstDoc = new quizz({
question: 'question 1',
id: 1
})
var secondDoc = new quizz({
question: 'question 2',
id: 2
var question_data = [firstDoc, secondDoc];
quizz.insertMany(question_data, function(err, res){
if(err){
console.log("error occured while saving document object " + err )
}else{
console.log("saved data");
}
})
quizz.findOne({id : '1'}, function(err, res){
if(err){
console.log(err)
}else{
console.log(res);
}
})
insertMany Will return you the list of _ids that have been created for your documents you've inserted. You can then pull out each document based on the _ids individually
quizz.insertMany(question_data, function(err, res){
if(err){
console.log("error occured while saving document object " + err )
}else{
console.dir(res); // res has the _ids.
console.log("saved data");
}
})
http://mongoosejs.com/docs/api.html#model_Model.insertMany
Alternatively if you always want to ensure ordering you could add a sequence column to the question, and/or put all questions inside one quizz.
if you want to do something with the _id of the documents that was inserted into the collection then use the answer of Kevin, but if you want to just do something with them later, you can use .find() which return you all the documents that are in the collection.
quizz.find(function(err, docs) {
//docs = array of all the docs in the collections
})
if you want specific by id:
quizz.findOne({_id: id},function(err, doc) {
//doc = the specific doc
})
if you want specific by strong
quizz.findOne({question: "question 3"},function(err, doc) {
//doc = the first (!!!) doc that have question in his `question` attribute
})
or if you want all the docs that have question 3 in them:
quizz.find({question: "question 3"},function(err, docs) {
//docs = array with all the docs that have "question 3" there, (return array even if only 1 found)
})

findOneAndUpdate doesn't make update

I am using mongoose with mean stack, I want to add a column age to my data saved in the database which contains a value of email 'a#a.a'
var MyModel = db.model('MyModel', userSchema);
var query = {'email' : 'a#a.a' };
MyModel.findOneAndUpdate(query,{ 'age': '20' } , {upsert:true},function(err, doc){
if (err) return res.send(500, { error: err });
//return res.send("succesfully saved");
console.log('check');
});
but when I run in the mongo shell db.users.find({"email" : "a#a.a" }) I can't see the column added
I don't need the variable MyModel, :
User.findOneAndUpdate(query,{ age: 'age1' } , {upsert:true},function(err, doc){

How to update document in mongo with nested schema

I have the following code:
add_new_patient : function(username,pname,pid,pdesc,callback){
var find_md = function(){
return function(err,pat){
if (err){
console.log('Error at adding patient: error at searching for users');
callback(2);//In the callback method I'm passing I have specific behavior for error handling for error codes.
return;
}
if (pat.lenth > 0){
console.log('searching for md');
MD.find({'mdname':username},add_patient(pat));
}else{
console.log('Error at adding patient: no user found');
callback(-1);
return;
}
}}
var add_patient = function(pat){
return function(err,md){
if (err){
console.log('Error at adding patient: cannot find md');
callback(-1);
return;
}
callback(0);
}
}
console.log('searching for user '+pid);
User.find({'name':pid},find_md());
}
And these are my schemas:
var mdSchema = mongoose.Schema({
mdname : String,
pacients : [userSchema.ObjectId]
});
var userSchema =mongoose.Schema({
name : String,
password : String,
phone : String,
history : [{timestamp: Date , heart: Number }],
md : {mdname: String, contact: Number}
});
As you can guess from the code I want to add patients to the dms. First I search for the pid in the database. If I find a patient I start to look for mds. When I find the md I want to add the patient to the md. Now I don't know how to add them. The schema shows that I have an array of schemaUser, which is the type of patient, but I don't know how to append to it, not how to create an MD model from object from the data I received from the query. Also what should I insert into the array of patients? The _id of the found patient or the whole object?
I managed to solve it in the following way:
var add_patient = function(pat){
return function(err,md){
if (err){
console.log('Error at adding patient: cannot find md');
callback(-1);
return;
}
var query = {mdname: md.mdname};
console.log(md);
var doThis = { $addToSet: { patients: pat._id } };
console.log(query);
MD.update(query,doThis,done_adding());
}
}
var done_adding = function(){
return function(err,dat){
if (err){
console.log('Error at the end of adding new patient!');
callback(-1);
return;
}
console.log('new patient added');
callback(0);
}
So what this does is: when I have the md to whom I want to add a patient/user I use the update method, with the $addToSet operation so I will have a set of patients associated with an md. I don't know why, but the same code did not work for me with the $push parameter. Then simply nothing happened and when I set the upsert option to true my whole record in the database was overwritten by the id.

Mongoose still saves a document when there is an error

I have a pre-save method defined when saving a document, as follows:
Org.pre("save",function(next, done) {
var Currency = require('./currency');
var cur = this.get('currency');
console.log("checking currency: " + cur);
Currency
.findOne({name: cur})
.select('-_id name')
.exec(function (err, currency) {
if (err) done(err);
if (!currency) done(new Error("The currency you selected ('" + currency + "') is not supported. Please select one from /currencies"));
next();
});
});
This method checks the currencies collection to see if the currency field input is supported. In testing my API, I get the appropriate error returned (500 error with the message: The currency you selected...), but the document is still saved in MongoDB. I would expect that when an error is sent the document should not be saved. Am I missing something here?
You're still calling next(); in the error case, so try rewriting that part as:
Currency
.findOne({name: cur})
.select('-_id name')
.exec(function (err, currency) {
if (err) return done(err);
if (!currency) return done(new Error("The currency you selected ('" + currency + "') is not supported. Please select one from /currencies"));
next();
});
Seems like by not putting the next() in brackets, the flow continues. I changed the exec function as follows in order for this to work:
if (err) {
done(err);
} else if (!currency) {
done(new Error("The currency you selected ('" + currency + "') is not supported. Please select one from /currencies"));
} else {
next();
}
Problem solved.

Resources