Basicly I want to check if a specific data exists in the database before inserting data(im using native mongodb driver), so what I tried is using collection.findOne() to check if data exists, if the property of the attribute is null the collection.insert() performs.
Apparently my code is not working according the logic, please someone enlighten me!
some of my code:
exports.addUser = function(req, res) {
var twitterId = req.body.provider;
var userEmail = req.body.email;
db.collection('users', function(err, collection) {
collection.findOne({'email':userEmail }, function(err, item){
if(item.email === null){
collection.insert({
'email': userEmail,
'provider': {
'twitter': {
'id': twitterId
}
}
}, function(err, result) {
if (err) {
res.send({'error':'An error has occurred'});
} else {
console.log('Success: ' + JSON.stringify(result[0]));
res.send(result[0]);
}
});
}else{
console.log("Email exits ");
}
});
});
}
Your if statement is expecting item.email to be explicitly set to null. If item.email is not a property of item, that if statement will evaluate to false.
var foo = {bar:'baz'}
foo.bar // 'baz'
foo.notSet // undefined
foo.notSet === undefined // true
foo.notSet === null // false
// now if we set foo.notSet to undefined...
foo.notSet = null // undefined
foo.notSet === null // true
So, there are few options...
if (item.email) {} else {};
if ('email' in item) {} else {};
if (item.hasOwnProperty('email')) {} else {};
If you try and call a property that does not exist on the object itself, JS will check it's prototype, if it doesn't exist on the prototype anywhere, then it will return undefined.
The in operator will check to see if the left side operand is a property of the right side object.
Finally Object.hasOwnProperty will check for it's argument as a property on the object.
All that to say, {upsert:true} would probably be your best bet.
Related
I'm trying to check if a user exists (registered on a json file).
Unfortunately I don't find a valid solution in all Stack Overflow that gives me a simple "true" in a callback.
The version closest to a solution
Experiment V1 :
let userExist;
function check(){
console.log("CHECK!");
return userExist = true;
}
// check(); if this, return true... obvious.
//// check if user exist
server.readFileSync(filepath, 'utf8', (err, data) =>
{
let json = JSON.parse(data),
userlist = json.allusers;
for (let key in userlist)
{
if ( userlist[key].email == req.body.user_email )
{
console.log("FINDED EQUAL");
check(); // return undefined ???
}
}
});
console.log("userExist value : "+userExist);
differently formulated the debugs also appear, but "true" never returns.
note: yes, JSON is read correctly. If everything works inside the readfile, you immediately notice the same emails.
output: "undefined"
Log: total bypassed
Experiment V2 :
In this case (with asynchronous reading) it returns all the debugging (but the "true" remains undefined)
The problem with the asynchronous is that I have to wait for it to check to continue with the other functions.
//// check if user exist
server.readFile(filepath, 'utf8', (err, data) =>
{
let json = JSON.parse(data),
userlist = json.allusers;
for (let key in userlist)
{
if (/* json.allusers.hasOwnProperty(key) &&*/ userlist[key].email == req.body.user_email )
{
console.log("FINDED EQUAL");
check();
}
}
});
var userExist;
function check(userExist){
console.log("CHECK!");
return userExist=true;
}
console.log("userExist value : "+userExist+"");
server listening on: 8080
userExist value : undefined
CHECK!
FINDED EQUAL
Experiment V3 :
after the various suggestions I come to a compromise by using the syntax for the async functions.
This allowed to reach an ordered code, but despite this it is not possible to wait for the results and export them out of the same function (this is because node itself is asynchronous! Therefore it has already gone on!)
using a "message" variable to check if it could return an object I did so:
//simple output tester
var message;
// create a promise
let loopusers = new Promise( (resolve)=>{
server.readFile( filepath, 'utf8',
(err, data) => {
let json = JSON.parse(data),
userlist = json.allusers,
findedequal;
console.log("CHECK USERS IN DB...for "+userlist.length+" elements");
// loop all items
for (let key in userlist)
{
console.log("Analyzed key ::: "+key);
if ( userlist[key].email == req.body.user_email )
{
console.log("CHECK : user isn't free");
findedequal=true;
resolve(true); // return the result of promise
}
else if(key >= userlist.length-1 && !findedequal )
{
console.log("CHECK : User is free ;)");
resolve(false); // return the result of promise
}
}
// call the action
createuser();
});
});
// when promise finished --> start action
async function createuser(message)
{
let userExist = await loopusers;
console.log("userExist: "+userExist);
if(userExist)
{
message = { Server: "This user already exists, Try new e-mail..."};
}
else
{
message = { Server: "Registration user -> completed..."};
}
// return values
return message;
};
It is also possible to use the classic syntax via "then". For exemple:
//simple output tester
var message;
// create a promise
let loopusers = new Promise( (resolve)=>{
...
});
loopusers.then( (response)=>{
...
})
Then I realized that it was easy to simplify even more by calling the functions directly from the initial one:
var message;
// create a promise --> check json items
server.readFile( filepath, 'utf8',
(err, data) => {
let json = JSON.parse(data),
userlist = json.allusers,
findedequal;
console.log("CHECK USERS IN DB...for "+userlist.length+" elements");
for (let key in userlist)
{
console.log("Analyzed key ::: "+key);
if ( userlist[key].email == req.body.user_email )
{
console.log("CHECK : user isn't free");
findedequal=true;
createuser(true); // call direct function whit params true
}
else if(key >= userlist.length-1 && !findedequal )
{
console.log("CHECK : User is free ;)");
createuser(false); // call direct function whit params false
}
}
});
// start action
function createuser(userExist)
{
if(userExist)
{
message = { Server: "This user already exists, Try new e-mail..."};
}
else
{
message = { Server: "Registration user -> completed!"};
}
// return values
return message;
};
debugging is taken and written
the message is lost outside the aSync function
Experiment V4 Final! :
Finally, after many attempts the solution! (Yes... But know it's not Async)
If we allocate in a variable the reading becomes synchronous the whole model and we return to the simple one
let message,
file = server.readFileSync(filepath, 'utf8'), // read sync
json = JSON.parse(file), // now parse file
userlist = json.allusers, // get your target container object
userExist,
findedequal;
console.log("CHECK USERS IN DB...for "+userlist.length+" elements");
for (let key in userlist)
{
console.log("Analyzed key ::: "+key);
if ( userlist[key].email == req.body.user_email )
{
console.log("CHECK : finded equal value on key ["+key+"] - user isn't free");
findedequal=true;
userExist = true;
}
else if(key >= userlist.length-1 && !findedequal )
{
console.log("CHECK : User is free ;)");
userExist = false;
}
}
if(userExist)
{
console.log("└ EXIT TO CHECK --> Can't create user, function stop.");
message = { Server: "This user already exists, Try new e-mail..."};
}
else
{
console.log("└ Exit to check --> New user registration ...");
message = { Server: "Registration user -> completed!"};
}
}
return message;
Now:
It's all sync and all log is perfect
all var is checked
all return... return
** Final conclusions: **
Is it possible to retrieve an ASync variable in node?
As far as I understand so far ... no.
Node is async by its nature, therefore recovering information that is not saved and then recovered from a DB is left behind among the things to do, becoming unrecoverable if you use it as in this post.
However ... if the purpose is to make reading a file synchronous, the answer was simpler than expected.
A special thanks to: Barmar; Austin Leehealey; C.Gochev;
The problem is that you are calling console.log("userExist value : "+userExist+"");
too early. At the moment that you call that line, userExist is not defined yet. This is because the server.readFile() function requires a callback and that callback function is executed once it has read the file. However, reading files often take time and so the program keeps going. It executes console.log("userExist value : "+userExist+""); and then goes back to the callback function and defines userExist as true.
If you want more information on what callbacks are look at the link below. Callbacks are a defining feature of Nodejs and understanding them is essential to any Node website.
https://medium.com/better-programming/callbacks-in-node-js-how-why-when-ac293f0403ca
Try something like this.
let userExist;
function check(){
console.log("CHECK!");
return userExist = true;
}
// check(); if this, return true... obvious.
//// check if user exist
server.readFileSync(filepath, 'utf8', (err, data) =>
{
let json = JSON.parse(data),
userlist = json.allusers;
for (let key in userlist)
{
if ( userlist[key].email == req.body.user_email )
{
console.log("FINDED EQUAL");
check(); // return undefined ???
console.log("userExist value : "+userExist);
}
}
});
When a user clicks "save" I need to collect all the data from inputs with a class of input_product and compile it to data with this format:
data = {param1:[{upc:'upc', value:'value'}, ... ], ... paramN: [ ... ]}
I tried doing this with the code below, but I keep getting this error:
Uncaught TypeError: Cannot read property 'push' of undefined
$('.save').on('click', function() {
event.preventDefault();
var data = {};
$('.input_product').each(function() {
const
param = $(this).attr('name'),
upc = $(this).parent().parent().attr('id'),
value = $(this).val()
console.log(param, upc, value); //prints qty, 1001, 5
if (value && param) {
if (!param in data) {
data[param] = [];
}
data[param].push({'upc':upc, 'value':value}); // Error is thrown here
}
});
window.someFunction(data);
});
What am I missing here?
The in operator has lower precedence than the ! operator. You need to add brackets around param in data; change
if(!param in data)
to
if(!(param in data))
Currently, what you are doing is converting the value of param to a boolean, negating that, and then checking if the result of that negation exists as a key in the object data (i.e., what you are writing is equivalent to if((!param) in data)) , when instead you want to check if param exists as a key in data and then negate the result of that to execute some code if param does not exist as a key in data. As a result, you are never setting the value of the key param in data, so it stays at undefined and you get the Uncaught TypeError: Cannot read property 'push' of undefined.
See Operator Precedence.
Try this:
$('.save').on('click', function() {
event.preventDefault();
var data = {};
$('.input_product').each(function() {
const
param = $(this).attr('name'),
upc = $(this).parent().parent().attr('id'),
value = $(this).val()
console.log(param, upc, value);
if (value && param) {
if (!(param in data)) {//added brackets
data[param] = [];
}
data[param].push({'upc':upc, 'value':value});
}
});
window.someFunction(data);
});
Working JSFiddle Demo: https://jsfiddle.net/n6bg3da8/
I have function that creates a team and puts data to database. Now I'm trying to check if team already exists, if it does exists then reply with message. I have problem with my if statement.
if (result[0].teamname == teamName)
When result[0].teamname is undefined it shows Cannot read property 'teamname' of undefined it ignores else and throws an error. How can I make so that does not ignore else?
Here is the function I use to create team.
function createTeam(teamName, members, message) {
teamName = teamName.replace("_", " ");
let insertTeam = `INSERT INTO teams (teamname) VALUES ('${teamName}');`;
db.select(`SELECT id_t, teamname FROM teams WHERE teamname = '${teamName}'`, function(err, result) {
if (err) {
throw err;
} else {
if (result[0].teamname == teamName) {
if (message.guild !== null) message.delete();
message.reply("this team already exists!");
} else {
db.query(insertTeam);
db.select(`SELECT id_t FROM teams WHERE teamname = '${teamName}'`, function(err, result) {
if (err) {
throw err;
} else {
for (let i = 0; i < members.length; i++) db.query(`INSERT INTO team_user (user, team) VALUES ('${members[i]}' , ${result[0].id_t})`);
}
});
if (message.guild !== null) message.delete();
let newTeam = new Discord.RichEmbed()
.setThumbnail("https://cdn.discordapp.com/emojis/542789472421675028.png?v=1")
.setColor("#15f153")
.addField("New team has been created!", `Team ${teamName} has been created with total of ${members.length} members!\nGood luck!`);
message.channel.send(newTeam);
}
}
});
What have I tried so far:
Checking if result[0].teamname is undefined
Checking if result length is not 0
try-catch statement
if (result[0] && result[0].teamname == teamName)
First of all you need to check if result[0] is not undefined
You need to short-circuit the condition. All this means is you want to first check that result exists before checking properties of result
So for example, your code should look like this:
if (result && result[0] && result[0].teamname == teamName) {
//Do something
}
If result is array with more then one value, then you need to iterate over every one of them, you can use filter array method for this:
var found = result.filter((row) => row.teamname == teamName);
if (found.length) {
}
You can also as #ThomasKleßen mention in comment check if result is not undefined:
var found = result && result.filter((row) => row.teamname == teamName).length;
if (found) {
}
You can always do a default value
if ((result || [{}])[0].teamname == teamName)
If the result is falsy, it will default to an array of an empty object, which will allow for the array access and dot notation to work, but the equality to fail.
Im trying to compute if an array has a particular object that has a value which matches to what I want
The array is membersArray and here is where it comes from
<firebase-query
id="querymembers"
path="/members"
order-by-child="crew"
equal-to="[[routeData.key]]"
data="{{membersArray}}">
</firebase-query>
The property
_isUserAMember: {
type: Boolean,
computed: '_computeIfIsMember(membersArray,user)'
},
And the function itself
_computeIfIsMember: function(membersArray, user) {
if(user && membersArray) {
// var found = false;
// for(var i = 0; i < membersArray.length; i++) {
// if (membersArray[i].userid === user.uid) {
// found = true;
// break;
// }
// }
// return console.log(found);
return console.log(membersArray.some(function(el) {
return el.crew === username;
}));
}
},
I keep getting false. What could I be doing wrong ?
This is how the members path looks like
console.log(typeof(this.membersArray)); // object
Assuming that firebase query will only return a result if the user.uid equal-to the child, I don't think you need to recheck the result.
How do I check if the "username" is equal to "name" and if it is the get the "id"?
So I'm trying to check if a name exists, if it does, then get the id.
var name="Lisa";
var users = [
{ id:"1234", username:"Claes", room: "General" },
{ id:"5678", username:"Lisa", room: "General" }
];
I have tried with this, but I don´t know what I´m missing?
for (username in users) {
if (!users.hasOwnProperty(username)) continue;
if (users[username]=name) {
nameexists = true;
id = users[id];
console.log('user exists'+users[id]);
}else{
nameexists = false;
console.log('user does not exist');
}
}
Any input really appreciated, thanks.
In Javascript, the syntax for (username in users) { .. is used to iterate the properties of an object, not an array.
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
To iterate an array use normal for, the Array's forEach method or the for..of syntax (ES6)
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array and https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of
Simple solution:
users.forEach(function(user) {
if (user.username) { // note this will expect a 'truthy' value i.e. except for false, 0, "", null, undefined, and NaN
nameexists = true;
id = user.id;
console.log('user exists'+user.id);
} else {
nameexists = false;
console.log('user does not exist');
}
}
BTW: checking equality uses '==' or '===', not '='.