How to Delete Item from Object in NodeJS/Mongo Service - javascript

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/

Related

Why the object returns undefined when output property?

At the server side with Node js, I am using Mongoose to query by the ID a document.
I queried a document from mongodb to use the ID of that document to add some data to it. But when I want to use de ID of that document it is undefined. Here is the code:
user.find({user: req.body.user}, function(err, doc) {
if(err) {
console.log(err);
} else {
console.log(doc + ' the document'); // Here returns the object with all properties
console.log(typeof doc + ' type of variable'); // Outputs Object
console.log(doc._id + ' the ID'); // Undefined
console.log(doc.user+ ' the user'); //Also undefined
user.findById(doc._id, function(err, user){
if(err) {
console.log(err);
} else {
console.log(user + ' <---');
// for (const iterator of req.body.list) {
// console.log(iterator);
// user.cases = iterator;
// user.save().then(person => {
// console.log('Added')
// })
// .catch(err => {
// console.log('Failed')
// });
// }
}
})
// console.log(doc + ' <--- Document');
}
});
})
Mongoose's Model.find() always provides documents inside of a collection, even if there's only 1. This method is a shorthand for calling Query.find(), which notes this more directly:
The result will be an array of documents.
With it, you'll have to access the desired document from the collection before accessing the _id.
user.find({user: req.body.user}, function(err, docs /* note: plural */) {
if(err) {
console.log(err);
} else if (docs.length === 0) {
console.log('Not found');
} else {
console.log(docs[0]._id, 'the user');
let userDoc = docs[0];
console.log(userDoc._id, 'the user');
// ...
}
});
You can alternately use Model.findOne() to get back only the first/single document that matches the query:
user.findOne({user: req.body.user}, function(err, userDoc) {
if(err) {
console.log(err);
} else if (userDoc == null) {
console.log('Not found');
} else {
console.log(userDoc._id, 'the user');
// ...
}
});

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

Can't Set Headers After they are sent - NodeJS

I have a node js app and one of the routes I keep getting "Can't set headers after they are sent error".
What the route does:
Users in my app have certain access levels so this route goes through the users accessLevel array and finds the appropriate access level for this route. And based on the access level of the user who's calling the route has it performs different actions.
The Code:
app.post('/bios/approve', isLoggedIn, function(req, res) {
for (var i = 0; i < req.user.accessLevel.length; i++) {
if (req.user.accessLevel[i] === "Bio Officer") {
Bio.findOneAndUpdate({userID: req.body.userID, bioForSector: req.body.bioForSector}, {
background: req.body.background,
experience: req.body.experience,
skills: req.body.skills,
bioStatus: req.body.bioStatus
}, function(err, editedBio) {
if (err)
console.log("Error while editing Pending Bio is " + err);
else if (editedBio) {
User.findOneAndUpdate({accessLevel: "Bio Designer"}, {
$push: {biosPending: editedBio._id}
}, function(err, user) {
if (err) {
console.log("The error while finding lineManager is " + err);
} else if (user) {User.findOneAndUpdate({accessLevel: "Bio Officer"}, {
$pull: {
biosPending: editedBio._id
}
}, function(err, bioOfficer) {
if (err) {
console.log("The error while finding lineManager is " + err);
}
res.json("Bio Done!")
});
}
});
}
});
} else if (req.user.accessLevel[i] === "Bio Designer") {
// Currently Empty
} else {
Bio.findOneAndUpdate({userID: req.body.userID,bioForSector: req.body.bioForSector}, {
background: req.body.background,
experience: req.body.experience,
skills: req.body.skills,
bioStatus: req.body.bioStatus
}, function(err, editedBio) {
if (err)
console.log("Error while editing Pending Bio is " + err);
else if (editedBio) {
User.findOneAndUpdate({accessLevel: "Bio Officer"}, {$push: {biosPending: editedBio._id}
}, function(err, user) {
if (err) {
console.log("The error while finding lineManager is " + err);
} else if (user) {
User.findOneAndUpdate({email: editedBio.lineManagerEmail}, {$pull: {biosPending: editedBio._id}
}, function(err, bioOfficer) {
if (err) {
console.log("The error while finding lineManager is " + err);
}
res.json("bio Done!")
});
}
});
}
});
}
}
});
Any help will be greatly appreciated. Does anyone know what am I doing wrong?
Can't Set Headers After they are sent
means you are sending response multiple times for a single request.
From you code what i can suggest is:
for (var i = 0; i < req.user.accessLevel.length; i++) {
if(--req.user.accessLevel.length == 0){
res.json("Bio Done!")
}
}
First try add res.End(); after res.json().
If that doesn't work can you please add the code of 'isLoggedIn'?
Every time you send back a response you should use the return word too. You want to return to make sure no code after the line gets executed and send another response again accidentally.
E.g.: return res.json("bio Done!")

Node.js mongodb trouble with callbacks

So I'm trying to create a sign up route that checks to see if the user exists first and i have the database call in a separate function that needs to return true or false when it's done. The problem is i'm not very familiar with callbacks and the whole asynchronous thing everything that i have searched for does not seem to work keeps giving me.
TypeError: callback is not a function
This is my code any help or direction would be appreciated.
function pullUserFromDatabase(username, callback) {
console.log(username); //for debug
mongodb.connect(url, function(err, db) {
if(err) {
console.log("didn't get far" + err) //for debug
}
var collection = db.collection(username);
collection.findOne({username}, function(err, item) {
if(err) {
console.log("nope it broke" + err) //for debug
} else {
console.log("it worked" + JSON.stringify(item)) //for debug
callback(true);
}
});
});
}
app.post("/signup", function(req, res) {
var username = req.headers["username"],
password = req.headers["password"],
randomSalt = crypto.randomBytes(32).toString("hex"),
passwordHashOutput = crypto.createHash('sha256').update(password + randomSalt).digest("hex");
if(!username || !password) {
res.send("Username or password not provided.")
} else if(pullUserFromDatabase(username)) {
res.send("User exist.")
}
});
You need to use the callback as follows:
function pullUserFromDatabase(data, callback) {
console.log(data.username); //for debug
mongodb.connect(url, function(err, db) {
if(err) {
console.log("didn't get far" + err) //for debug
}
var collection = db.collection(data.collection);
collection.find({"username": data.username}).count(function (err, count) {
callback(err, !! count);
});
});
};
app.post("/signup", function(req, res) {
var username = req.headers["username"],
password = req.headers["password"],
randomSalt = crypto.randomBytes(32).toString("hex"),
passwordHashOutput = crypto.createHash('sha256').update(password + randomSalt).digest("hex");
if(!username || !password) {
res.send("Username or password not provided.")
}
var data = {
username: username,
collection: "collectionName"
}
if(!username || !password) {
res.send("Username or password not provided.")
}
pullUserFromDatabase(data, function(err, exists) {
if (err) {
res.send(400, "Error - " + err);
}
else if(exists) {
res.send(200, "User exists.");
}
res.send(200, "User does not exist.");
});
});
The reason that callback is undefined is because you didn't pass a 2nd argument to pullUserFromDatabase(username) Provide a 2nd argument, eg. pullUserFromDatabase(username, function(result) {/* do something here with the result variable */})
If you're not very familiar with aync & callbacks, you might find it more intuitive to use promises, but that comes with its own learning curve.
In the context of the original code, this looks like:
...
if(!username || !password) {
res.send("Username or password not provided.");
return;
}
pullUserFromDatabase(username, function(result) {
if(result) {
res.send("User exist.");
} else {
// TODO: Handle this case. If res.send() is never called, the HTTP request won't complete
}
});
...
Also, you need to ensure your callback is always invoked. Add callback(false):
console.log("nope it broke" + err); //for debug
callback(false);
Do a similar step after "didn't get far" and then return so the callback doesn't get invoked multiple times.

Mongoose / JavaScript - Saving error - undefined object

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.

Categories

Resources