I have an issue with extracting value from object. I want to check if my SQL table have the asked row:
var checkRow = function(connection,chekedColumn,chekParam, checkVal){
connection.query('SELECT EXISTS(SELECT '+ chekedColumn +' FROM asterisk.users where ' +chekParam+'='+checkVal+')', function (err, rows) {
if(err) console.log('SQL suerry error')
else {
console.log(rows[0]); // output: { 'EXISTS(SELECT id FROM asterisk.users where name=1600)': 1 }
return (rows[0]);
};
});
};
but returned value from query is an object, and return(rows[0]) give just [object object] output. How can I extract value of this object?
You can use
Object.keys(obj)
to get the values of the object. See api reference for more info.
EDIT:
Just to elaborate abit more on this... how you'd go about getting it out is this.
// get the keys of the source
var keys = Object.keys( source );
// loop through the keys
for ( var i = 0; i < keys.length; i++ ) {
var key = keys[i];
var value = source[key];
//do something with value
}
The output is an object which you don't know. So try either:
console.log("Result: %j", rows[0]);
console.log(JSON.stringify(rows[0]));
console.log(require('util').inspect(rows[0], false, null));
to view the structure. After you know the keys, use it to access the data.
Thanks all for helps and for your ideas. Dmitry Matveev help me to understand how to identify object properties(Objekt.keys()). And thanks to user568109 for reminding of asynchronous function, so I use callback. Final code:
var checkRow = function(connection,chekedColumn,chekParam, checkVal,callback){
connection.query('SELECT EXISTS(SELECT '+ chekedColumn +' FROM asterisk.users where ' +chekParam+'='+checkVal+')', function (err, rows) {
if(err) console.log('SQL suerry error')
else {
var keys=Object.keys(rows[0]);
keys.forEach(function(key) {
callback(rows[0][key]);
});
};
});
};
And for using this functions we need to call it like:
checkRow(connection,'id','name',name,function(value){
console.log(value)
})
Related
i am sending following text in body parameter
[{"full_image":"alskdfhlkjasvbuialsdvlasljkvbaslvjhbalfdghbakjldfgjlajkshfiuqr","type":"jpg"},{"full_image": "alskdfhlkjasvbuialsdvlasljkvbaslvjhbalfdghbakjldfgjlajkshfiuqr","type":"jpg"}]
and then parsing it JSON.pasrebut i am unable get get lenght and loop the json. following is the code.
var images = req.body.images;
JSON.parse(images, function(key,value){
var counter = key.length;
var seaWeedPicture = {};
var base64FullImage = value;
seaweedfs.write(new Buffer(base64FullImage, 'base64')).then(function (pic) {
var seaWeedPicture = {
picture: config.seaWeedURL + '/' + pic.fid
};
}).catch(function(err){
console.log(err);
res.format({
json: function () {
res.send({
status: 200,
data: []
});
}
});
});
the generated error is [TypeError: must start with number, buffer, array or string]
You can get length by Object constructor
var length=Object.keys(images).length;
//Do your loop with `length`
console.log(Object.keys(images).length);//2
var record = [{"full_image":"alskdfhlkjasvbuialsdvlasljkvbaslvjhbalfdghbakjldfgjlajkshfiuqr","type":"jpg"},{"full_image": "alskdfhlkjasvbuialsdvlasljkvbaslvjhbalfdghbakjldfgjlajkshfiuqr","type":"jpg"}]
console.log(record.length);
for(var i=0;i<record.length;i++){console.log(record[i]['full_image']);}
Do like this:
I am working with NodeJS using ExpressJS framework in a mysql backend. I am running a query inside a for loop and my loop and work afterwards depends on the return value of the query. I am not very good with mysql query so I am running it through a for loop.
The problem is, due asynchronous [I guess!], the for loop ends long before the query result comes out.
Here is my code:
function search_people_step2(user_id, search_criteria, user_friend)
{
var first_name_friends = [];
var last_name_friends = [];
for(var i = 0; i < user_friend.length; i++)
{
con.query("SELECT first_name, second_name FROM user WHERE userid = ?", user_friend[i],function(err, rows)
{
if(err)
{
//error;
}
else
{
if(rows.length == 0)
{
//nothing gets returned
}
else {
console.log(rows);
first_name_friends[i] = rows[0].first_name;
last_name_friends[i] = rows[0].second_name;
}
}
});
}
Now,I can get the value (using console.log) inside the query statement, however, on the outside, the value becomes empty (undefined) since the rest of the code has already been computed.
How can I solve this?
Thanks in advance.
The first thing that I find weird in your code is that you are not using an IN statement in your SQL query (not directly related to your problem though) which means you are making as many requests as there are entries in user_friend. The problem is that the SQL library is implemented asynchronously and you cannot avoid it. BUT you can handle it elegantly with Promises which are ES6 features:
(I didn't test the code but I think it should work)
function search_people_step2(user_id, search_criteria, user_friend)
{
return new Promise((resolve,reject)=>{
var first_name_friends = [];
var last_name_friends = [];
var placeHolders=user_friend.map(()=>"?").join(",");
con.query("SELECT first_name, second_name FROM user WHERE userid IN ("+placeHolders+")",user_friend,(err,rows)=>{
if(err)
reject(err);
else{
rows.forEach(row=>{
first_name_friends.push(row.first_name);
last_name_friends.push(row.second_name);
});
resolve({first_name_friends,last_name_friends});
}
});
});
}
And call your function like this :
search_people_step2(id,crit,friends).then(result=>{
//handle result asynchronously as there is no choice
console.log(result.first_name_friends);
console.log(result.last_name_friends);
}).catch(err=>{
//handle error
});
You are right, your problem is the asynchronous nature of the mysql call. You have to provide a callback to your search_people_step2 function.
You may change it like this:
search_people_step2(user_id, search_criteria, user_friend, callback)
In your function body you may use a library called async to handle all the callbacks properly. Here is an example for the usage:
async.eachSeries(user_friend, function(item, eachCb){
con.query("SELECT first_name, second_name FROM user WHERE userid = ?",
user_friend[i],function(err, rows) {
if(err) {
eachCb('error');
}
else {
if(rows.length == 0){
//nothing gets returned
eachCb(null);
}
else {
console.log(rows);
first_name_friends.push(rows[0].first_name);
last_name_friends.push(rows[0].second_name);
eachCb(null);
}
}
}, callback);
});
This calls each query in order on every item of the array and calls the inner callback if finished. When all items are processed or an error occured the outer callback is called. See the async library for further documentation.
simplest solution is
function search_people_step2(user_id, search_criteria, user_friend)
{
var first_name_friends = [];
var last_name_friends = [];
for(var i = 0; i < user_friend.length; i++)
{
con.query("SELECT first_name, second_name FROM user WHERE userid = ?", user_friend[i],function(err, rows)
{
if(err)
{
//error;
}
else
{
if(rows.length == 0)
{
//nothing gets returned
}
else {
console.log(rows);
first_name_friends[i] = rows[0].first_name;
last_name_friends[i] = rows[0].second_name;
}
if(i==user_friend.length-1){
//do your work here which you want to perform in end
}
}
});
}
or use async library
var async = require('async');
var first_name_friends = [];
var last_name_friends = [];
async.series([function(cb){
function search_people_step2(user_id, search_criteria, user_friend)
{
for(var i = 0; i < user_friend.length; i++)
{
con.query("SELECT first_name, second_name FROM user WHERE userid = ?", user_friend[i],function(err, rows)
{
if(err)
{
//error;
}
else
{
if(rows.length == 0)
{
//nothing gets returned
}
else {
console.log(rows);
first_name_friends[i] = rows[0].first_name;
last_name_friends[i] = rows[0].second_name;
}
if(i==user_friend.length-1){
cb()
}
}
});
}
},function(cb){
//do your work here
}],function(err){})
var sender_username = req.session.user_id;
var recipient_username = req.body.recipient_username;
var content = req.body.content;
var sql = ' SELECT sender_username, recipient_username, COUNT(recipient_username) as count FROM message WHERE sender_username = "'+sender_username+'" AND recipient_username = "'+recipient_username+'" GROUP BY sender_username LIMIT 1 ';
var message_no = 0;
var data;
connection.query(sql, function(err, result) {
if (err) {
res.send(err);
}
else {
data = result;
// res.send(data); < - this works
// res.send(result); <- this works
// res.send(result.count); <- undefined
}
});
res.send(data); // undefined (can't seem to save to variable after connection.query())
The res.send(result); seems to work. It gives:
[{"sender_username":"sender","recipient_username":"recipient","count":2}]
I am just trying to get the value for count and save that to a variable, but things like result.count are returning undefined for some reason.
It's because the JSON is an array, so you should access it like the following
res.send(result[0].count);
Using a prior example? How could I insert/update a mysql table using
a JSON object without manually naming the table column headers? And insure it async.
var mysql = require('node-mysql');
var conn = mysql.createConnection({
...
});
var values = [
{name:'demian', email: 'demian#gmail.com', ID: 1},
{name:'john' , email: 'john#gmail.com' , ID: 2},
{name:'mark' , email: 'mark#gmail.com' , ID: 3},
{name:'pete ' , email: 'pete#gmail.com' , ID: 4}
];
// var sql = "INSERT INTO Test (name, email, n) VALUES ?";
conn.query(sql, [values], function(err) {
if (err) throw err;
conn.end();
})
You could do something like this:
for(var i = 0; i < values.length; i++){
var post = values[i]
var query = connection.query('INSERT INTO posts SET ?', post, function(err, result) {
// Finish
});
}
EDIT
This is how you inserts multiple 'posts' at once.
INSERT INTO posts (type, details)
VALUES
('Helen', 24),
('Katrina', 21),
You would have to loop through the first value to get the names like this.
var names = [];
for(name in values[0]){
names.push(name);
// That would give you name, email, id
}
Then you would have to create your own string to insert.
var newvalues = [];
for(var i = 0; i < values.length; i++){
newvalues.push('(' + values[i].join(',') + ')');
}
Then to execute the query:
connection.query('INSERT INTO posts (' + names.join(',') + ') VALUES ' + newvalues.join(',') , function(err, rows, fields) {
// Result
});
You would have to test the code yourself, this is just how you would do it.
Look at the 'Custom Format' part here. If you notice, this example using named placeholders in the query, allowing you to pass an object, and the placeholders are replaced with the matching attributes from the object. I've also pasted the relevant section for clarity:
connection.config.queryFormat = function (query, values) {
if (!values) return query;
return query.replace(/\:(\w+)/g, function (txt, key) {
if (values.hasOwnProperty(key)) {
return this.escape(values[key]);
}
return txt;
}.bind(this));
};
connection.query("UPDATE posts SET title = :title", { title: "Hello MySQL" });
You could create a small function that maps an array with that format to an insert statement.
You can easily loop through the fields and use some string concatenation.
Better option is (using MySQL Connection):
app.get('/yourcontroller/:id', function (req, res) {
var id = req.params.id;
var dataUpdate = req.body;
connection.query(
'UPDATE yourtable SET ? Where ID = ?',
[dataUpdate, id],
function (err, result) {
if (err) throw err;
console.log('Updated data ! Changed ' + result.changedRows + ' rows');
}
);
});
I have a code to do some calculation.
How can I write this code in an asyn way?
When query the database, seems we can not get the results synchronously.
So how to implement this kind of feature?
function main () {
var v = 0, k;
for (k in obj)
v += calc(obj[k].formula)
return v;
}
function calc (formula) {
var result = 0;
if (formula.type === 'SQL') {
var someSql = "select value from x = y"; // this SQL related to the formula;
client.query(someSql, function (err, rows) {
console.log(rows[0].value);
// *How can I get the value here?*
});
result = ? // *How can I return this value to the main function?*
}
else
result = formulaCalc(formula); // some other asyn code
return result;
}
Its not possible to return the result of an asynchronous function, it will just return in its own function scope.
Also this is not possible, the result will always be unchanged (null)
client.query(someSql, function (err, rows) {
result = rows[0].value;
});
return result;
Put a callback in the calc() function as second parameter and call that function in the client.query callback with the result
function main() {
calc(formula,function(rows) {
console.log(rows) // this is the result
});
}
function calc(formula,callback) {
client.query(query,function(err,rows) {
callback(rows);
});
}
Now if you want the main to return that result, you also have to put a callback parameter in the main and call that function like before.
I advice you to check out async its a great library to not have to deal with this kind of hassle
Here is a very crude way of implementing a loop to perform a calculation (emulating an asynchronous database call) by using events.
As Brmm alluded, once you go async you have to go async all the way. The code below is just a sample for you to get an idea of what the process in theory should look like. There are several libraries that make handling the sync process for asynch calls much cleaner that you would want to look into as well:
var events = require('events');
var eventEmitter = new events.EventEmitter();
var total = 0;
var count = 0;
var keys = [];
// Loop through the items
calculatePrice = function(keys) {
for (var i = 0; i < keys.length; i++) {
key = keys[i];
eventEmitter.emit('getPriceFromDb', {key: key, count: keys.length});
};
}
// Get the price for a single item (from a DB or whatever)
getPriceFromDb = function(data) {
console.log('fetching price for item: ' + data.key);
// mimic an async db call
setTimeout( function() {
price = data.key * 10;
eventEmitter.emit('aggregatePrice', {key: data.key, price: price, count: data.count});
}, 500);
}
// Agregate the price and figures out if we are done
aggregatePrice = function(data) {
count++;
total += data.price;
console.log('price $' + price + ' total so far $' + total);
var areWeDone = (count == data.count);
if (areWeDone) {
eventEmitter.emit('done', {key: data.key, total: total});
}
}
// We are done.
displayTotal = function(data) {
console.log('total $ ' + data.total);
}
// Wire up the events
eventEmitter.on('getPriceFromDb', getPriceFromDb);
eventEmitter.on('aggregatePrice', aggregatePrice);
eventEmitter.on('done', displayTotal);
// Kick of the calculate process over an array of keys
keys = [1, 2, 3]
calculatePrice(keys);