Mongoose / JavaScript - Saving error - undefined object - javascript

I am trying to save a match between 2 teams, I am passing the 2 teams through a drop down list.
When I use util.log to output the homeTeam to the console when INSIDE the Team.findByKey method it works successfully and here is the output:
3 Mar 19:52:33 - { name: 'Liverpool',
_id: 51312074bb176ba624000007,
__v: 0,
key: 1362174068837 }
But as soon as I try to do this outside of this method I get the following output which means that when I try to save this as a match, the hometeam appears as just undefined rather than the id of the hometeam:
3 Mar 19:54:09 - [object Object]
My problem is that I am eventually wanting to save both a home team and an away team to the same match in one save. The code for saving a match works when inside the Team.findByKey method which is as follows:
app.get('/save/matchTest', function(req, res) {
var key = 1362174006191; // Man Utd 51312036bb176ba624000001
Team.findByKey(key, function(err, team) {
util.log(team);
if(err) {
util.log("Error occured");
}
if(!team) {
util.log("The team does not exist");
}
var match = new Match({
hometeam: team._id
});
match.save(function(err) {
if(err) {
util.log('Error while saving Match: ' + util.inspect(err));
res.send("An error occured whilst saving the match");
} else {
res.send("Saved the match");
}
});
});
});
But what I want to do is to be able to save a match with the following
var match = new Match({
hometeam: homeTeam._id,
awayteam: awayTeam._id
});
Does anyone have any ideas?
Here is the relevant code:
JavaScript
submitMatch = function(){
var homeId = $("#homeTeamList").val();
var awayId = $("#awayTeamList").val();
//alert("home: " + homeId + " away: " + awayId);
// Frontend sends the data
var matchForm = {
homeKey : $('#homeTeamList').val(),
awayKey : $('#awayTeamList').val()
};
// Basic validation
$.post('/save/match', {'matchForm' : matchForm}, function(response) {
console.log(response);
});
};
/save/match
app.post('/save/match', function(req, res) {
util.log('Serving request for url [GET] ' + req.route.path);
// Output to console to test what is being passed to Save Match
// Entire body passed to console
//console.log('body: ', req.body);
// Entire matchForm from body
//console.log('matchForm: ', req.body.matchForm);
// Home Key from matchForm
//console.log('homeKey: ', req.body.matchForm.homeKey);
// Away Key from matchForm
//console.log('awayKey: ', req.body.matchForm.awayKey);
// Get data from match Form
var matchForm = req.body.matchForm;
// Check if a match with 2 teams has been submitted
if(matchForm.homeKey === '' || matchForm.homeKey === undefined ||
matchForm.awayKey === '' || matchForm.awayKey === undefined){
// Not a valid match
util.log('Not valid match');
} else {
var homeId = matchForm.homeKey;
var awayId = matchForm.awayKey;
var homeTeam = Team.findByKey(homeId, function(err, homeTeam) {
util.log(homeTeam);
if(err) {
util.log("Error occured");
}
if(!homeTeam) {
util.log("The home team does not exist");
}
});
var match = new Match({
hometeam: homeTeam._id
});
//util.log(match);
}
});

In /save/match you're using the value of homeTeam in the Match constructor before it's been set by the callback. You need to create the Match inside both the home and away team findByKey callbacks like this:
Team.findByKey(homeId, function(err, homeTeam) {
util.log(homeTeam);
if(err) {
return util.log("Error occured");
}
if(!homeTeam) {
return util.log("The home team does not exist");
}
Team.findByKey(awayId, function(err, awayTeam) {
util.log(awayTeam);
if(err) {
return util.log("Error occured");
}
if(!awayTeam) {
return util.log("The away team does not exist");
}
var match = new Match({
hometeam: homeTeam._id,
awayteam: awayTeam._id
});
});
});
To look up the home and away teams in parallel while still keeping your code organized, you'll want to look at using a flow control library like async.

Related

How to avoid overwrite of existing file json object in node

I am trying to solve an issue where I am trying to write a json file with user input details. But each time I input new details it is overwriting the existing data.
How can I avoid overwriting existing json object in a json file and add new object in the array instead based on user input ?
userData.json:
[
{
"name": "Name",
"number": "4334343",
"email": "email#email.com",
"message": "sdsd"
}
]
server.js :-
app.get("/myaction", function (request, response){
var name = request.query.name;
var number = request.query.number;
var email = request.query.email;
var message = request.query.message;
if (name != "") {
response.send("Your name is " + name + "number"+ number + "email"+ email + "message" + message);
const sendData = [{
name:name,
number:number,
email:email,
message:message
}];
fs.stat('./userdata.json', function(err, stat) {
if(err == null) {
console.log('File exists');
} else if(err.code === 'ENOENT') {
// file does not exist
var data = JSON.stringify(sendData,null, 2);
fs.writeFile('./userdata.json', data, (err) => {
if (!err) {
console.log('done');
}
});
} else {
console.log('Some other error: ', err.code);
}
});
} else {
response.send("Please provide info");
}
});
In order to append data instead of replacing it you can pass a+ flag to fs.writeFile:
fs.writeFile('./userdata.json', data, { flag: 'a+' }, (err) => {
if (!err) {
console.log('done');
}
});
It will create the file if the file does not exist. If the file exists, then the content will be appended.
Here is the dirty way to do it:
fs.readFile('./userdata.json', (err, data) => {
if (err){
console.log(err);
} else {
obj = JSON.parse(data);
obj.push(sendData);
json = JSON.stringify(obj);
fs.writeFile('./userdata.json', json, callback);
}});
Everytime you want to add a record, read the array, append to it and dump it again. However, consider switching to a database to avoid this.

mongoose findone return undefine

I have a bot. It can input some text and return some word.
I would like to use MongoDB. Because Heroku can't store data.
So I add function.js that use mongoose.
console.log('data.functionswitch = ' + data.functionswitch);
console log is work fine. It can reply what i want.
return data.functionswitch;
but return data.functionswitch only return undefined when i call it in input.js/.
I have try async/await.
But it only stops working.
How can I improve it and make it work? Thank you.
-
-
2018/03/15 updated
function.js
function switchfind(id, name, callback) {
mongodb.functionSwitch.findOne({
groupid: id, functionname: name
}, function (err, data) {
if (err) {
console.log(err);
callback(null);
return;
}
else if (!data) {
console.log("No record found")
callback(null);
return;
}
console.log('date = ' + data);
console.log('data.functionswitch = ' + data.functionswitch);
callback(data.functionswitch);
return;
})
};
input.js
function parseInput(rplyToken, inputStr) {
//console.log('InputStr: ' + inputStr);
_isNaN = function (obj) {
return isNaN(parseInt(obj));
}
let msgSplitor = (/\S+/ig);
let mainMsg = inputStr.match(msgSplitor);
let trigger = mainMsg[0].toString().toLowerCase();
exports.mongoose.switchfind(mainMsg[1], mainMsg[2], function (functionswitch) {
console.log('functionswitch = ' + functionswitch)
if (functionswitch === null) {
console.log('HERE === NULL ')
}
if (functionswitch == 0) {
console.log('HERE != 0')
return;
}
else if (functionswitch != 0 ) {
console.log('HERE != 0')
if (inputStr.match(/\w/) != null && inputStr.toLowerCase().match(/\d+d+\d/) != null) return exports.rollbase.nomalDiceRoller(inputStr, mainMsg[0], mainMsg[1], mainMsg[2]);
}
})
}
update
const mongoose = require('mongoose');
let uristring = process.env.mongoURL ||
'mongodb://XXXXXXX';
mongoose.connect(uristring);
mongoose.connect(uristring, function (err, res) {
if (err) {
console.log('ERROR connecting to: ' + uristring + '. ' + err);
} else {
console.log('Succeeded connected to: ' + uristring);
// console.log('allswitch: ' + allswitch);
}
});
var functionSchema = new mongoose.Schema({
groupid: String,
functionname: String,
functionswitch: String
});
// Compiles the schema into a model, opening (or creating, if
// nonexistent) the 'PowerUsers' collection in the MongoDB database
var functionSwitch = mongoose.model('functionSwitchs', functionSchema);
The problem in your code is that you are using findOne as it was synchronous. You cannot simply return the data, you have to use a callback.
Here is a tutorial about callbacks.
Example of what it should look like :
// The find function
function switchfind(id, name, callback) {
mongodb.functionSwitch.findOne({
groupid: id,
functionname: name
}, function (err, data) {
// Handle error
if (err) {
callback(null);
return;
}
// Handle empty data
if (data == null) {
callback(null);
return;
}
// Handle with data
callback(data.functionswitch);
})
};
// How to call it
funcX() {
switchfind(id, name, function (functionswitch) {
if (functionswitch === null) {
// Handle the error
}
// Handle the data
});
}

nodejs mongoDB findOneAndUpdate(); returns true even after database is updated

i am working on an Ionic-1 + nodejs + angular application. My mongoDb findOneAndUpdate() function returns true on each call even the first call updates database.
nodejs:
app.post('/booking', function (req, res) {
var collection = req.db.get('restaurant');
var id = req.body.id;
var status = req.body.status;
collection.findOneAndUpdate({status: status, id: id},{$set:{status:"booked"}}, function (e, doc) {
console.log(id, status);
if (e) {
console.log(e);
}
else if(!doc) {
res.send(false);
}
else {
res.send(true);
}
});
});
controller.js
$scope.bookMe = function(id){
var Obj = {status: "yes", id: id};
myService.booking(Obj).success(function(res){
console.log(Obj, "Checking status")
console.log(res);
if (res == true) {
var alertPopup = $ionicPopup.alert({
title: 'Booking Confirm',
template: 'Thanks For Booking'
});
}
else{
var alertPopup = $ionicPopup.alert({
title: 'Error',
template: ' Not available'
});
}
})
};
where i am doing wrong. my DB gets updated but it returns true always on next call.
The documentation about findOneAndUpdate says :
Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes immediately if callback is passed.
So it's regular behavior you got a doc.
Note:
Since you are checking availability status="yes", Better hard code, instead of getting it from request query/data.
Change the response according to your requirement res.send(true)/ res.send(false).
Following code will work
app.post('/booking', function (req, res) {
var collection = req.db.get('restaurant');
collection.findOneAndUpdate({
status: "yes",
_id: req.body.id
}, {
$set: {
status: "booked"
}
}, function (err, result) {
//Error handling
if (err) {
return res.status(500).send('Something broke!');
}
//Send response based on the required
if (result.hasOwnProperty("value") &&
result.value !== null) {
res.send(true);
} else {
res.send(false);
}
});
});

nodejs-javascript update object

I'm new to nodejs and trying to write a function to update and object on mongodb.
Here is my fundtion that is under routs/rates.js. Briefly, the function is called whenever a button/link called "like" is clicked and it should update the total number of like this item has recieved. Item is an object in my mongodb.
router.put('/update_likes', function (req, res) {
var sessionId = req.sessionID;
var queryId = req.body.queryId;
var item = req.body.item;
var itemId= req.body.itemId;
var commentsNum= req.body.commentsNum;
var category= req.body.category;
var find_condition = {
'item': item,
'sessionId': req.sessionID,
'category': category,
'commentsNum': commentsNum
};
var update_callback = function (err, item_obj) {
if (err)
return console.log('An error occurred: ', err);
var update = {
$inc: { 'totalLikes': 1 },
$push: {
'likes': {
'itemId': itemID,
'sequence': item_obj.totalLikes + 1
}
}
};
Query.update(find_condition, update, function (err) {
if (err)
return console.log('[UPDATE] ', err);
});
}
Query.findOne(find_condition, update_callback);
res.sendStatus(200);});
Using the function above, gives me an error that totalLikes is undefined in line 15. What I understant is that I cannot use item_obj inside var update = {}, but I actually don't know how to solve this issue in another way.
Any hints? or suggested enhancements to the code?

How to Delete Item from Object in NodeJS/Mongo Service

I'm querying for a user object and performing a series of updates on the items within compared to incoming postdata (jsObject). I'm wondering how to completely remove an item from the object...specifically a Date object (user[0].birthDate)...before I make a save of the updated user object.
orm.User.find({ appId: appId, facebookUsername:usersFBUsername}).exec(function (error, user) {
if (error) {
console.log('Error in User Query: ' + error);
}
else if(Object.keys(user).length > 0) {
if(jsObject.name != null)
user[0].name = jsObject.name;
if(jsObject.email != null)
user[0].emailAddress = jsObject.email;
if(jsObject.birthDate != null && jsObject.birthDate.length > 0) {
user[0].birthDate = jsObject.birthDate;
}
else {
console.log('delete it');
//orm.User.update({_id:user._id}, {$pull:{birthDate:1}});
//delete user[0].birthDate;
}
}
user[0].save(function (error) {
if (error != null) {
console.log('An error has occurred while saving user:' + error);
response.end(results.getResultsJSON(results.ERROR, error));
}
else {
console.log(' [User Successfully Updated]');
response.end('{ "success": ' + JSON.stringify(user[0]) + ' }');
}
});
});
You can see in the commented code some attempts I've made which have not been successful. I even gave this a try after the save completed, which also did not work:
orm.User.update({appId: appId, facebookUsername:usersFBUsername},{$pull:{birthDate:deleteBirthDate}})
.exec(function(error){
if(error) {
console.log('oh well: ' + error);
}
else {
console.log('maybe maybe');
}
});
I appreciate any suggestions.
Chris
$pull is for removing values from arrays, but you can use $unset:
orm.User.update(
{_id : user._id},
{ $unset : { birthDate : 1 }},
function(err, numAffected) {
...
}
);
For reference:
https://docs.mongodb.com/manual/reference/operator/update/unset/

Categories

Resources