I have this code:
var sql1 = "SELECT DISTINCT sensor_id, timestamp FROM Displacement_Record WHERE wave_type = 1 ORDER BY timestamp ASC";
var sql2 = "SELECT timestamp FROM Displacement_Record WHERE wave_type = 0 AND sensor_id = ?";
var sql3 = "SELECT latitude, longitude FROM Sensor_Record WHERE sensor_id = ?";
var pTime, sTime;
db.getConnection((err, conn) => {
if (err) throw err;
conn.query(sql1, function (err, res, fields) {
if (err) throw err;
for (i = 0; i < res.length; i++) {
var sensor = res[i].sensor_id;
console.log(sensor);
var pTime = res[i].timestamp;
sql2 = mysql.format(sql2, sensor);
conn.query(sql2, function (err, results, fields) {
if (err) throw err;
var sTime = res[i].timestamp; //timestamp error
console.log("results = " + results + " " + results.length);
conn.query(sql3, function (err, res, fields) {
if (err) throw err;
var location = [res[i].latitude, res[i].longitude];
console.log("Data = " + sensor + " " + pTime + " " + sTime + " " + latitude + " " + longitude);
});
});
}
});
conn.release();
});
The first query give me the results properly. I am able to get and store the data I need. However, the second and third query results as:
results = [object Object],[object Object],[object Object]
and throws:
throw err; // Rethrow non-MySQL errors
^
TypeError: Cannot read property 'timestamp' of undefined
I tried to see what causes this. I am able to get a proper result only when I remove the condition in the query. However, I need the condition of course. And I'm also wondering how come it throws error in the following queries when I am able to get results on the first query, with conditions and all.
I hope somebody can help me, thanks!
The problem is actually not really a problem. when you have [object Object] in any console.log, it means that what you want to print in a string is not possible to print as a string.
If you really want to print the result, what you should do instead of
conn.query(sql2, function (err, results, fields) {
if (err) throw err;
console.log("results = " + results + " " + results.length); // HERE
conn.query(sql3, function (err, res, fields) {
if (err) throw err;
var location = [res[i].latitude, res[i].longitude];
console.log("Data = " + sensor + " " + pTime + " " + sTime + " " + latitude + " " + longitude); // HERE
});
});
Is actually :
conn.query(sql2, function (err, results, fields) {
if (err) throw err;
console.log("results ="); // HERE
console.log({ results }, results.length); // HERE
conn.query(sql3, function (err, res, fields) {
if (err) throw err;
var location = [res[i].latitude, res[i].longitude];
console.log("Data = "); // HERE
console.log({ sensor, pTime, sTime, latitude, longitude }); // HERE
});
});
See the notation console.log({ variable });
This allows you to log your variable content, with the key displayed on the left, as you'd actually want to do in your current console.logs.
Example :
const results = [1, 2, 3, 4];
const randomString = 'Some content in here';
console.log({ results, randomString});
This outputs :
You can't console combination of string and object at once time.
Try below format, It might help you.
console.log('results =');
console.log(results);
console.log(results.length);
Related
My code is supposed to retrieve the "DropsRemaining" for a user ID (which it does successfully) and then -1 from the number it retrieves. When retreiving the data it returns this string "[ RowDataPacket { DropsRemaining: 5 } }" however the end of the code does not -1 from the DropsRemaining it instead sets the DropsRemaining to -1. If anyone can help fix this I'd really appreciate it.
var sql = "SELECT DropsRemaining FROM UserData WHERE DiscordID LIKE " + message.author.id;
var DropCount = [];
connection.query(sql, function (err, result) {
if (!err)
setValue(result);
else
console.log("No Information For That User Found");
});
function setValue(value) {
DropCount = value;
console.log(DropCount);
};
//Remove drop from user
DropCount = DropCount - 1;
var sql = "UPDATE UserData SET DropsRemaining = " + DropCount + " WHERE DiscordID = " + message.author.id;
The problem is that the order you write your Javascript code is not exactly how it is performed in the end.
When you call the connection.query() function, the next line of code does not necessarily already have the result of that function.
I would recommend you to have a look on this book series, they have really good explanations about those characteristics.
Probably the following code will output the expected response. Notice that I nested the code, therefore I can control the flow properly.
var sql = "SELECT DropsRemaining FROM UserData WHERE DiscordID LIKE " + message.author.id;
// Get the DropsRemaining
connection.query(sql, function (err, result) {
if (!err) {
// No errors in the query, decrement the Drops
decrementDrop(result);
} else {
console.log("No Information For That User Found");
}
});
function decrementDrop(dropsAvailable) {
var dropsRemaining = dropsAvailable - 1;
var updateSql = "UPDATE UserData SET DropsRemaining = " + dropsRemaining + " WHERE DiscordID = " + message.author.id;
// Update the DropsRemaining column to the dropsRemaining, i.e., decrement the DropsRemaining column value
connection.query(updateSql, function (err, result) {
if (!err) {
console.log("DiscordID = " + message.author.id +" has " + dropsRemaining + " drops remaining")
} else {
console.log("Error!");
}
});
}
I have a Node.js app that is writing data to a MySQL backend. One field is an array I stringify. I can see in the workbench the data is correct when in the database. However when I retrieve it I am getting an error when I try to parse it.
"Unexpected token o in JSON at position 1"
If I log the result it shows up as [Object Object].
From what I read online this means it is already a JS object and I do not need to parse it. However I cannot find anything about how to get access to the data.
process: function (bot, msg, suffix) {
var ftcmds = suffix.split(" ", 1);
var ftName = ftcmds[0];
var ftArray;
var selectSQL = "SELECT FireTeam FROM fireteam WHERE Name = '" + ftName + "'";
var updateSQL = "UPDATE fireteam SET FireTeam = '" + ftArray + "'WHERE Name = '" + ftName + "'";
mysqlcon.query(selectSQL, function (err, result) {
console.log("Result |" + result);
console.log("Error |" + err);
if (err) {
console.log("Caught Error " + err + " " + msg.author);
}
else {
console.log("Recovered result " + result);
ftArray = result;
console.log("Attempting to update array");
ftArray.push(msg.author.id);
console.log("updated array " + ftArray);
var jsonArray = JSON.stringify(ftArray);
mysqlcon.query(updateSQL, function (err, result) {
console.log("Result |" + result);
console.log("Error |" + err);
if (err.toString().indexOf(dupErr) != -1) {
msg.author.send("Could not find that fireteam");
console.log("Error: Did not locate the requested name " + msg.author)
} else if (err) {
console.log("Caught Error " + err + " " + msg.author);
}
else {
msg.author.send("You have joined Fireteam " + name + ". I will setup a group chat on " + date + " if your team fills up.");
}
})
}
});
}
You should just be able to access it as an object, so if result has fields name and title you can just access them as:
var name = result.name
var title = result.title
I am trying to store details of affectedRows from a MySQL INSERT query using NodeJS. My mind is melting trying to comprehend callbacks and Promises. Being a single-man dev team I wanted to reach out and ask for the clearest explanation as to how a callback can be applied here in a foreach loop.
The goal should be clear from these few lines of code; store data in the affected_rows[] array.
var affected_rows = [];
asset_array.forEach(function(asset) { // Populate the asset table
var query_string = "INSERT IGNORE INTO " + asset_table + " SET symbol = '" + asset[0] + "', name = '" + asset[1] + "'";
connection.query(query_string, function(err, rows, fields) {
if (err) throw err;
if ( rows.affectedRows > 0 ) {
data_to_push = [asset_table, asset[0], asset[1]];
affected_rows.push(data_to_push);
}
});
});
console.log(affected_rows); // [] for obvious async reasons
One option would be to process the asset_array inside a function and pass a callback into it and when loops through asset_array check if the current index matches the asset_array length (-1). If so call the callback.
var affected_rows = [];
function processAssets(cb) {
var array_len = asset_array_len.length
asset_array.forEach(function(asset, index) {
var query_string = 'INSERT IGNORE INTO ' + asset_table + ' SET symbol = \'' + asset[0] + '\', name = \'' + asset[1] + '\'';
connection.query(query_string, function(err, rows, fields) {
if (err) throw err
if (rows.affectedRows > 0) {
data_to_push = [asset_table, asset[0], asset[1]];
affected_rows.push(data_to_push);
}
if (index === (array_len - 1)) cb()
});
});
}
processAssets(function() {
console.log(affected_rows)
})
Will suggest you to have a look at async Queue.
You can change your code like this to use it.
//2nd Step - Perform each task and then call callback() to move to next task
var q = async.queue(function(query_string, callback) {
connection.query(query_string, function(err, rows, fields) {
if (err) throw err;
if ( rows.affectedRows > 0 ) {
data_to_push = [asset_table, asset[0], asset[1]];
affected_rows.push(data_to_push);
}
callback(); //call next task
});
}, 2); //here 2 means concurrency ie 2 tasks will run in parallel
//Final Step - Drain gives you end of queue which means all tasks have finished processing
q.drain = function() {
//Do whatever you want after all tasks are finished
};
//1st Step - create a queue of all tasks that you need to perform
for (var i = 0; i < asset_array.length ; i++) {
var query_string = "INSERT IGNORE INTO " + asset_table + " SET symbol = '" + asset[0] + "', name = '" + asset[1] + "'";
q.push(query_string);
}
I am pretty new to nodejs and async worlds.
The case is, I have an array like var ids = [1, 2, 3, 4];
I need to update mytable according to sequence of the array element. So I do something like:
sort: function(ids, callback) {
// dont worry about this
this.create_connection();
this.connection.connect();
for(var i=0; i<ids.length;i++) {
var q = "UPDATE mytable SET sequence="+i+" where id="+ids[i]+"; ";
this.connection.query(q, function(err, result) {
// I am not sure about this
// callback(err);
});
}
// I need to return callback at the end
// return callback();
this.connection.end();
}
But yes.. it does not work because I have to return callback.. I think I need to do the query syncronously.. I am not sure. Please help thanks.
If you are new to async worlds, you should take a look at module 'async'.
You can then do something like this :
async.forEachOfSeries(ids, function(id,index,callback){
var q = "UPDATE mytable SET sequence="+index+" where id="+id+"; ";
this.connection.query(q, function(err, result) {
callback();
});
},function done(){
// whatever you want to do onces all the individual updates have been executed.
})
See my inline comments:
sort: function(ids, callback) {
this.create_connection();
this.connection.connect();
var q = "UPDATE mytable SET sequence CASE id ";
// Don't execute one query per index in ids - that's inefficient
// Instead, pack up all the queries and execute them at once
for(var i=0; i<ids.length;i++) {
q += "WHEN " + ids[i] + " THEN " + i + " ";
}
q += "ELSE sequence END;";
// The sort method will return the result of connection.query
return this.connection.query(q, function(err, result) {
// End the connection
this.connection.end();
if(err) {
// Handle any error here
return callback(err);
}
// Otherwise, process, then return the result
return callback(err, result);
});
}
And here's something slightly more elegant:
sort: function(ids, callback) {
this.create_connection();
this.connection.connect();
// Don't execute one query per index in ids - that's inefficient
// Instead, pack up all the queries and execute them at once
var q = ids.reduce(function(pv, cv, ci){
return pv + " WHEN " + cv + " THEN " + ci + " ";
}, "UPDATE mytable SET sequence CASE id ") + " ELSE sequence END;";
// The sort method will return the result of connection.query
return this.connection.query(q, function(err, result) {
// End the connection
this.connection.end();
if(err) {
// Handle any error here
return callback(err);
}
// Otherwise, process, then return the result
return callback(err, result);
});
}
And you can replace the .reduce in the previous example with the following, if you want to use ES6 arrow functions:
var q = ids.reduce((pv, cv, ci) => pv + " WHEN " + cv + " THEN " + ci + " ",
"UPDATE mytable SET sequence CASE id ") + " ELSE sequence END;";
I'm trying to run this piece of code:
setInterval(function () {
var params = {
QueueUrl: 'https://sqs.us-east-1.amazonaws.com/821808622769/Teste', // required
MaxNumberOfMessages: 10
};
sqs.receiveMessage(params, function (err, data) {
if (err)
console.log('Erro de SQS:' + err);
else {
var retorno = data.Messages;
for (var i in data.Messages) {
var queryString = 'SELECT now()'; //dummy query, just for tests
db_connection.query(queryString, null, function (err, rows, fields) {
if (err) {
console.log('Erro no BD:' + err);
return;
}
var date = new Date();
console.log(retorno[i].Body + ' ' + date.getTime().toString());
});
}
console.log();
}
});
}, 30000);
and I have 5 messages in AWS SQS, such as this:
but when I run my code, instead of having the retorno[i].Body of each message, sometimes I get a message repeated, as show in this image
My for loop is running from 1 to 5 queries, but how do I carry the retorno[i] inside the callback to the database query? I mean, how do I identify which message I was dealing with?
Using .bind() you can setting the internal version of i to be the same as the version of i in your loop.
.bind({i:i}) at the end of your callback and change the internal code to reference this.i
for (var i in data.Messages) {
var queryString = 'SELECT now()'; //dummy query, just for tests
db_connection.query(queryString, null, function(err, rows, fields) {
if (err) {
console.log('Erro no BD:' + err);
return;
}
var date = new Date();
console.log(retorno[this.i].Body + ' ' + date.getTime().toString());
}.bind({
i: i
});
}
}