I am trying to get a list of distinct values from a MySQL Column and return these in a single JSON array.
I have this current code:
app.get('/experiences/', function(req, res) {
res.setHeader('Access-Control-Allow-Origin', http://localhost:3000');
connection.query('SELECT DISTINCT experience FROM questions', function(err, data) {
err ? res.send(err) : res.json(data);
});
});
I want the result to look like:
{experience: ["1-3","1-5","5+"]}
but it currently looks like:
[{"experience":"1-3"},{"experience":"1-5"},{"experience":"5+"}]
You can reformat the data object you get by looping on the array and recreate an object with the correct format.
Like this :
connection.query('SELECT DISTINCT experience FROM questions', function(err, data) {
if(err)
res.send(err)
else {
let experiences = [];
data.forEach(function(
experiences.push(d.experience);
}
result = {experience : experiences };
res.json(result);
}
});
Related
I have a table containing an ISBN number and a the available number of books. I want to make a query to to ISBN number and get the response about the number of the books with this ID, but I don't know how to write the proper function to get the query result?
db.checkPeldanyszam( rentISBN, response, callback) => {
if (err) {
res.status(500).render('error', { message: `Insertion unsuccessful: ${err.message}` });
} else {
console.log(err);
next();
}
});
exports.checkPeldanyszam = (req,callback) => {
console.log(req);
const query = `SELECT Peldanyszam, IF(Peldanyszam>0, "Jo", "Hibas") as isOkay FROM konyv
WHERE ISBN=${req};`
pool.query(query,callback);
}
Thank you.
I am working with Node.js (express) and MySQL and I have had problems trying to make several queries in the same route. The error it throws is:
Can't set headers after they are sent.
And my code is this:
router.post('/test', function (req, res, next){
db.query("select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where
TABLE_NAME = 'registros';", function (error, results, fields) {
if (error) throw error;
res.render('test', {
columnNames: results
});});
db.query("SELECT * FROM registros", function (error, resp, fields) {
if (error) throw error;
res.render('test', {
dataRegistros: resp
});});
});
I understand that it may be because it is rendering twice in the same route. What would be the correct method to make several SQL queries and return them to a file in view?
Regards!
According to mysql nodejs driver you can setup it o combine the queries and return an array with results
You must set this when you create the connection:
mysql.createConnection({multipleStatements: true});
Then make the request with both queries
router.post('/test', function (req, res, next) {
var queries = [
"select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'registros'",
"SELECT * FROM registros"
];
db.query(queries.join(';'), function (error, results, fields) {
if (error) throw error;
res.render('test', {
columnNames: results[0], // First query from array
dataRegistros: resp // Second query from array
});
});
});
But let me ask a question, why would you need to query column names when actually you query all rows and can get columns from there?
To make several queries from a single route use async npm library
npm install --save async
then use parallel method and functions to make the several queries for database with the callback.
async.parallel({
one: function(callback) {
callback(null, 'abc\n');
},
two: function(callback) {
callback(null, 'xyz\n');
}
}, function(err, results) {
if (error) throw error;
res.render('test', {
columnNames: results.one,
dataRegistros: results.two
});
});
Here is my efforts :
async.waterfall([
function(nextCall){
MongoClient.connect(url, function(err, db) {
if (err) throw err;
const dbo = db.db("testmdb");
const criteria = {"_id":ObjectId(id)};
console.log("paymentInof[] ::: ",paymentInfo)
let obj = paymentInfo[0];
const query = {
$push:{payment:obj}
};
dbo.collection("Invoice").update(criteria, query);
db.close();
nextCall(null,{code:200});
});
}
],function(err,results){
if(err) return err;
if(results.code === 200)
console.log(chalk.blue(' ::: all done ::: '));
next();
});
Input from api explorer :
{
"payment":[{"transaction_at":"2018-02-12T06:04:35.279Z","paid_amount":350,"patient_id":"1233sssdd33","patient_urn":"214125","invoice_amount":700,"user":"me"}],
"updated_by": "me"
}
Everything working fine but unable to push instead overwriting the existing object in payment array.
While from mongo shell it is working fine.
Please help me , where I am doing wrong ?
Thanks.
I think you need to check mongoose update upsert option.
Update options
There are several option values that can be used with an update
multi - update all records that match the query object, default is false (only the first one found is updated)
upsert - if true and no records match the query, insert update as a new record
raw - driver returns updated document as bson binary Buffer, default:false
Please check the documentation to here.
Use following code,
async.waterfall([
function(nextCall){
MongoClient.connect(url, function(err, db) {
if (err) throw err;
const dbo = db.db("testmdb");
let criteria = {"_id": ObjectId(id)};
let obj = paymentInfo[0];
let query = { $push: { payment: obj } }
dbo.collection("Invoice").update(criteria, query, {upsert:true});
db.close();
nextCall(null,{code:200});
});
}
],function(err,results){
if(err) return err;
if(results.code === 200)
console.log(chalk.blue(' ::: all done ::: '));
next();
});
Also please check the similar type of question to here and here.
Hope this will help you!!
I've been using mountebank to do some stubbing for performance testing and its an awesome tool. The functional teams have asked if it can be repurposed to support functional testing and I'd said i'd have a look.
What I want to achieve is to select from a mysql database an account number and its account balance and then return the balance to the client (in this case a jmeter harness)
function (request, state, logger) {
logger.info('GBG - getAccountBalance');
var mysql = require('mysql');
var result = '';
var con = mysql.createConnection({
host: "localhost",
user: "user",
password: "password",
database: "customer"
});
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
});
con.query('select * from accounts', function (err, rows, fields) {
if (err) throw err;
console.log(rows);
console.log('accountNumber is : ', rows[0].accountNumber);
result = rows[0].accountNumber;
});
console.log('result is : ', result);
var response = result;
return {
headers: {
'Content-Type': 'application/xml',
'Connection': 'Keep-Alive'
},
body: response
};
}
The result of the console log is:
result is :
Connected!
[ RowDataPacket { accountNumber: 777777, accountBalance: 777 } ]
accountNumber is : 777777
Not sure what I'm doing wrong and why the result is : lines comes up first despite being later in the code.
Any advice appreciated.
Full disclosure, I've been using mountebank for about two weeks so I'm a real beginner.
The function keyword inside connect and query is called callbacks, and only executed after the function itself is done. so your code would look like:
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
con.query('select * from accounts', function (err, rows, fields) {
if (err) throw err;
console.log(rows);
console.log('accountNumber is : ', rows[0].accountNumber);
result = rows[0].accountNumber;
console.log('result is : ', result);
var response = result;
});
});
and so on, but you just introduced callback hell to your code.
async is your friend.
EDIT:
following an example:
async.waterfall([
function (callback) {
//do some async function here
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
//call this when you are done
//you can even pass param to next function
callback(null,true);
});
},function (isConnected,callback1) {
if !(isConnected){
console.log("Connection failed! Skipping Query...")
callback1(null,"Error");
}
//do another async function here:
con.query('select * from accounts', function (err, rows, fields) {
if (err) throw err;
console.log(rows);
console.log('accountNumber is : ', rows[0].accountNumber);
result = rows[0].accountNumber;
callback1(null,"Complete");
});
}
], function (err,result) {
if(result == "Error"){
alert("Someting went wrong!");
}
if(result == "Complete"){
alert("Done!");
}
return 0;
});
note:I haven't written JS for awhile. Written this off of some existing code and haven't been tested. Also, Promise is also something that would help, but haven't looked into personally. BlueBird is a library for that.
The simplest way to get Data form mysql database using Promise and async await.
Get data dynamically by providing id to the SQL query.
With the help of following code snippet. First Your query will get execute fully the other process will execute.
response will be sent after execution of query is fully done. (sometimes response is sent first then execution of query completes)
async function getData(customerId){
let sql = `SELECT * FROM customer_info WHERE customerID = ${customerId}`
await connection.query(sql, (err, result) => {
data = {
CustomerId : result[0].customerID,
FirstName: result[0].FirstName,
LastName: result[0].LastName
}
})
}
function connectToDB(customerId){
return new Promise((resolve, reject) => {
getData(customerId).then(()=>resolve())
})
}
app.get('/customer/:id', (req, res) => {
let customerId = req.params.id
// Caller Function to all functions
async function callerFun(){
await connectToDB(customerId);
res.send("Execution Done");
}
callerFun();
})
I use backbone and need to nest Answers in Questions and Questions in Categories.
My problem is the data I get from MySQL.
I would like to have an array I can easily use with backbone, starting at the top (Category) and nest down to the bottom (Answers).
[Category1: [Question1: [Answer1: {...} ] ] ]
I use the following query to get all my MySQL data:
var getRecord = function(callback) {
var options = {
sql: 'SELECT * FROM Categories ' +
'LEFT JOIN Questions ON Categories.idCategories = Questions.idCategory ' +
'LEFT JOIN Answers ON Questions.idQuestions = Answers.idQuestion ',
nestTables: true
}
req.app.sql.query(options, function(err, result) {
if (err)
return callback(err, null)
outcome.record = result
return callback(null, 'done')
})
}
And the output looks something like this:
[
0: [CategoryObj, QuestionObj, AnswerObj]
1: ...
]
The MySQL Node Package does not nest 1:n relations, instead it creates an array with the length of most matches, so in the case I have 2 Categories, with each two Questions, with each two Answers -> Array length of 8, because I have 8 Answers in total.
But I cannot nest this array, in backbone collections without writing crazy loops and hacks.
Am I doing something wrong in the query or is there a packages that does the parsing job?
(I'm used to MongoDB (using embedded documents was quite easy) and now I have to use MySQL for this project..)
This is the MySQL Node Package on npm
There is nothing wrong with the package or how you use it. It just gives you the results returned by MySQL. As you probably know, MySQL itself does not format its results in a "nested" way when you're dealing with 1:n relations. If you use JOINs, it will give you a table with a row for each result it found. As it's a "table-formated" result, all rows have the same number of cells.
You can try to see the result of your request in PHPmyAdmin for example.
Thus, you have to post-format the results. There are probably modules to do that, but I have never used one yet.
If you want to do it yourself, you could do something like :
var nestedResult = {};
result.forEach(function(val){
var category = val[0],
question = val[1],
answer = val[2];
if (!nestedResult[category]){
nestedResult[category] = {};
}
if (!nestedResult[category][question]){
nestedResult[category][question] = [];
}
nestedResult[category][question].push(answer);
});
Which will give you something like :
{
"mysql" : {
"what is JOIN" : ["answer 1 blabla....","answer 2 blabla"],
"innoDB vs MyISAM" : ["answer 1","answer 2"]
},
"php" : {
"why no php 6 ?" : ["answeeeerr"]
}
}
I ended up parsing it myself. For some reason I was not able to find a well working ORM helper, that could do this job for me. Anyway I tried to avoid this solution, but here you go if you have the same problem one day this might help.
var async = require('async')
var getAnswers = function (id, callback) {
req.app.sql.query('SELECT * FROM Answers WHERE idQuestion LIKE ?', [id], function(err, result) {
if (err)
return callback(err, null)
return callback(null, result)
})
}
var getQuestions = function (id, callback) {
req.app.sql.query('SELECT * FROM Questions WHERE idCategory LIKE ?', [id], function(err, result) {
if (err)
return callback(err, null)
// Pair answers to questions
async.times(result.length, function(n, next) {
getAnswers(result[n].idQuestions, function (err, answers) {
result[n].answers = answers
next(err, result[n])
})
}, function(err, questions) {
callback(null, questions)
})
})
}
var getRecord = function(callback) {
req.app.sql.query('SELECT * FROM Categories', function(err, result) {
if (err)
return callback(err, null)
// Pair questions to categories
async.times(result.length, function(n, next) {
getQuestions(result[n].idCategories, function (err, questions) {
result[n].questions = questions
next(err, result[n])
})
}, function(err, final) {
callback(null, final)
})
})
}
var asyncFinally = function(err, results) {
if (err)
return next(err)
// we call results[0] because async.times leaves all the categories in there..
// sendSomewhere( results[0] )
}
async.parallel([getRecord], asyncFinally)