How to get only the value of a stringified MySQL query result? - mysql

After executing this query:
con.query("SELECT name FROM members WHERE id=1", function(err, rows, fields) {
console.log(rows);
});
this is what I get:
[ RowDataPacket { name: 'John' } ]
I expect only one record and I only want to get John. How do I do that?

Short of writing your own additional function(s) and passing the row object through them your desired result format is not possible based on the design of the mysqljs/mysql package. In a standard SELECT query the result is always an object.
There is a bit of a hack workaround by using the stream function. Below is an example, but you will still end up with more lines of code than you would if you simply accessed the value via rows[0].name in a standard query.
let the_query = con.query('SELECT name FROM members WHERE id = 1;');
the_query
.on('result', function(row) {
console.log('row.name:', row.name);
// expected in log:
// row.name: John
})
.on('end', function() {
// this chained event can be excluded
// here for demo purposes
console.log('all done');
});

JSON.stringify(RowDataPacket[0].name)
This will output:
John

Related

Cannot Get Data From Nested SQL Query

const getCompanyShifts = (req, res) => {
try {
const { company_id } = req.params;
connection.query(
`SELECT * FROM jobs WHERE company_fk=${company_id}`,
(err, rowss) => {
if (!err) {
connection.query(
`SELECT * FROM shift WHERE isBooked=1 AND fk_job = ?`,
[rowss.jobsID],
(err, rows) => {
if (err || rows.length === 0) {
res.status(404).json({
success: false,
message: "Company Shifts Not Found!",
err,
});
} else {
const shifts = [];
rows.forEach((row, i) => {
const shift = {
shiftID: rows[i].shiftID,
shiftStartTime: rows[i].startTime,
shiftEndTime: rows[i].endTime,
shiftDate: rows[i].date,
isBooked: rows[i].isBooked,
fk_job: rows[i].fk_job,
fk_guard: rows[i].fk_guard,
};
shifts.push(shift);
});
res.status(200).json({
success: true,
message: "Successfully Retrieved Company Shifts!",
shifts,
});
}
}
);
} else {
res.status(404).json({
success: false,
message: "Company Jobs Not Found!",
});
}
}
);
} catch (error) {
res.status(500).json({
success: false,
message: error.message,
});
}
};
in the first query of the above code, i am getting all the rows from the jobs table. In the second nested query, i am trying to get all rows from the shift table for each of the jobsID returned from the 1st query. But i don't get any data back. The data exists and it should return data but i don't get any data back. What am i doing wrong here ? Please help!
i assume there is a misunderstanding on how the data gets returned and therefore how the second query would work. According to your statement:
[...] i am getting all the rows from the jobs table. In the second nested
query, i am trying to get all rows from the shift table for each of
the jobsID returned from the 1st query. But i don't get any data back.
You are getting multiple rows back. So the first query works. But getting multiple rows back would result in rowss being an array. Therefore rowss.jobsID which is used as input for the next query isn't a correct use of an array and i expect the value of that expression to be undefined which will then result in the second query not returning anything.
To prove that add console.log(rowss) like so:
[...]
connection.query(
`SELECT * FROM jobs WHERE company_fk=${company_id}`,
(err, rowss) => {
console.log(rowss);
[...]
To solve the issue, i suggest to use sql capabilities and issue a join. By doing so, the Database will join the two tables, then returning only rows that fulfill the where condition. The combined statement should look like:
SELECT * FROM jobs WHERE company_fk=${company_id} LEFT JOIN shift ON shift.fk_job = jobs.jobsID WHERE isBooked=1
Hint: Depending on your DB schemes for ob'sand shift you might need to expand the * and list all table names explicitly, e.g. SELECT jobs.jobsID, jobs.<xyz>, shift.isBooked, shift.fk_job [...] FROM [...]. If you have column with same name in both tables, you might need to resolve the conflict which is caused by the join while combining the columns for returning the results like so: SELECT [...] shift.<xyz> as shift_xyz [...] FROM ...[].
As a plus, you also just need one SQL query instead of two.

Node Mysql undefined field on multiple queries

I'm using node, express, mysql
I'm doing multiple sql queries
app.get("/surveys/:id/edit", function (req, res) {
var q =
"\
SELECT * FROM inference_db.surveys WHERE surveys.slug=?; \
SELECT * FROM inference_db.imagez; \
SELECT city_id, name, province FROM inference_db.cities WHERE cities.type != 1;"
connection.query(q, [req.params.id], function (error, results, fields) {
if (error) throw error;
console.log(results[0]);
console.log("------------participating cities----------------- ");
console.log(results[0].participating_cities);
res.render("edit.ejs", {
pageTitle: "xdit Survey",
items1: results[0], // survey
items2: results[1], // imagez
items3: results[2] // cities
});
});
});
When I console log results[0], it is working and gives me all the fields.
But when I console log results[0].participating_cities, i get undefined. I need that field because I will pass it as an array. That field is a string stored in mysql table. Can anyone please help. Thanks!
My console log:
topic_id: 1,
featured: 1,
image: 'imee_marcos.jpg',
slug: 'test-html-Mar-06-2019',
status: '1',
participating_cities: '30,40',
participating_groups: '2,3' } ]
------------participating cities-----------------
undefined
results will be an array of query results for each of the queries you ran; but each of those results is an array in itself. So you probably want to check out the value of results[0][0].participating_cities if you want to get that field from the first row of the first result.

Node + Mysql: How to execute more queries based on another query

I'm pretty new to the node world and trying to migrate our php application to node. To be able to return all article data several different queries have to be done depending on the results of the first query. Currently my data object is empty as it's returned before the two queries run. How can I "chain" these queries using a promised based approach.
I found a library https://github.com/lukeb-uk/node-promise-mysql which I think could help but I have no idea how to implement it with my code.
exports.getArticleData = function(req, done) {
pool.getConnection(function(error, connection) {
if (error) throw error;
var data = {
article: {},
listicles: []
};
// Inital query
connection.query(
`SELECT article_id, title, is_listicle_article, FROM com_magazine_articles AS article WHERE article_id = ${req
.params.articleId}`,
function(error, results) {
data.article = results;
}
);
// This query should only be excuted if is_listicle_article = true
if (data.article.is_listicle_article) {
connection.query(
`SELECT * FROM com_magazine_article_listicles WHERE article_id = ${req.params
.articleId}`,
function(error, results) {
data.listicle = results;
}
);
}
// More queries depending on the result of the first one
// ....
// ....
// Callback with the data object
done(data);
connection.release();
});
};
What would be the best approach to execute queries based on other queries results? Any help is really appreciated.
The functionality you are looking for is Promise chaining, it allows you to construct a sequence of promises, each depending on the result of the previous value. Applying this to your code, you would get something like this:
exports.getArticleData = function(req, done) {
pool.getConnection(function(error, connection) {
if (error) throw error;
// Inital query
return connection.query(
`SELECT article_id, title, is_listicle_article, FROM com_magazine_articles AS article WHERE article_id = ${req
.params.articleId}`
).then((rows) => {
return Promise.all(rows.map((article) => {
if (article.is_listicle_article) {
return connection.query(
`SELECT * FROM com_magazine_article_listicles WHERE article_id = ${req.params
.articleId}`
);
} else {
return Promise.resolve(null);
}
}));
}).then((res) => {
connection.release();
done(res.filter(function(i){ return i != null; }));
})
// This query should only be excuted if is_listicle_article = true
// More queries depending on the result of the first one
// ....
// ....
// Callback with the data object
connection.release();
});
};
Obviously since I don't have all of your code, I couldn't verify this example, but this should be roughly the functionality you are looking for. That said, I think there were a couple of mistakes you should watch out for in your example code:
connection.query() returns a promise (aka doesn't need a callback function). Use this functionality to your advantage- it will make your code prettier.
connection.query() returns an array of rows, not a single value. You seemed to ignore this in your example code.
Try not to save things into a variable when using promises, it isn't necessary. To remedy this, read more into the Promise API (Promise.resolve(), Promise.reject(), Promise.any(), Promise.catch(), Promise.all()) etc.
It seems like these SQL queries could easily be combined into a single query. This will be way more efficient that performing two operations. Not sure if this is the case with the remaining queries you wish to use, but definitely something to look out for.

Simple Express program for querying a result

I have a snippet of Express code
Below what i am trying to do is pass the table name to keyName by extracting from the request
But I am facing deaslock
i wanted to know whether i am following proper protocols for JSON response
[Part-of-Express-Code]
app.get('/RestaurantDesc/:Key',function(request,response,next){
var keyName=request.query.Key;
var name_of_restaurants, RestaurantTimings;
async.series( [
// Get the first table contents
function ( callback ) {
connection.query('SELECT * FROM ',keyName, function(err, rows, fields)
{
console.log('Connection result error '+err);
name_of_restaurants = rows;
callback();
});
},
// Get the second table contents
function ( callback ) {
connection.query('SELECT * FROM RestaurantTimings', function(err, rows, fields)
{
console.log('Connection result error '+err);
RestaurantTimings = rows;
callback();
});
}
// Send the response
], function ( error, results ) {
response.json({
'restaurants' : name_of_restaurants,
'RestaurantTimings' : RestaurantTimings
});
} );
} );
I am getting the output as Cannot GET /RestaurantDesc/
Any Ideas
your route should be path, A path that you can access through GET request.
for ex: you should be able to access it through
http://example.com/RestaurantDesc/anyKeyHere
and in your code you have
var keyName = request.query.Key
req.query contains query variables see http://expressjs.com/api.html#req.query
So your keyName variable won't contain anyKeyHere.
req.params.Key will contain value anyKeyHere;
but you will need to pass it in url path.
if you need to pass key data in query you can do this.
app.get('/RestaurantDesc',function(request,response,next){
var keyName=request.query.Key;
});
and pass key like this in your url
http://example.com/RestaurantDesc/?Key=restaurnetkeyHere
Try going through guide in express site and understand routings and how it works.
If you getting "Cannot GET /RestaurantDesc/" is because you have not setup this route, try /RestaurantDesc/something. request.query is used for search terms, ie things that come after a questionmaek in a url. Use request.param.Key instead.
Also for best practices you should lowercase resource names and use the shorter req/res instead of request/response.

Using node-mysql in a function

I'm very new to nodejs and have a question.
Trying to create a function that will call the value of any field where I mention its ID from a table:
function getUserInfo (userID, dynamicField) {
var query = connection.query('SELECT '+dynamicField+' from users WHERE userID = '+connection.escape(userID));
query.on('result', function(row) {
return(row.dynamicField);
});
};
console.log(getUserInfo(8, userEmail)) //this should get me the userEmail value of the user with userID=8
However, I get "undefined". If I use console.log rather than return, it logs the value but this has no use as a function to be used inside other functions to get a value.
I will be glad if I can get help for modifying the function.
This is a common mistake amongst async/nodejs beginners. You have essentially wrapped an async function inside a sync function which breaks down the nature of node's event loop. The return expression needs to be replaced with a callback. See below:
// Method
function getUserInfo (userID, dynamicField, callback) {
var query = connection.query('SELECT '+dynamicField+' from users WHERE userID = '+connection.escape(userID));
query.on('result', function(row) {
callback(null, row.dynamicField);
});
};
// Implementation
getUserInfo(8, userEmail, function(err, result){
console.log(err || result);
});
By convention, in Nodejs we always pass an error object first in the callback. In this case since there is no error to capture, we pass null in its place.