How to save data to mysql server with Node.js - mysql

I am currently trying to build an application for my project.
It is my first time programming as well as using node.js
I have successfully connected node.js with mysql and was able to save data to mysql server.
However, some data that I want to save is declared as undefined
currently my code looks like this
imap.once('ready', function() {
openInbox(function(err, box) {
if (err) throw err;
imap.search([ 'UNSEEN', ['SINCE', 'December 20, 2018'] ], function(err, results) {
if (err) {
console.log('you are already up to date');
}
//var f = imap.fetch(results, {markSeen: true, bodies: ''});
var f = imap.fetch(results, {bodies: ''});
f.on('message', function(msg, seqno) {
var prefix = '(#' + seqno + ') ';
msg.on('body', function(stream, info) {
simpleParser(stream, (err, mail) => {
con.connect(function(err) {
console.log("Connected!");
var sql = "INSERT INTO scrap (reply_to, content) VALUES ('" + mail.from.text + "', '" + mail.subject +"')";
con.query(sql, function (err , result) {
});
});
console.log(mail.from);
// console.log(mail.from.text);
// console.log(mail.subject);
// console.log(mail.text);
});
the Console.log will fetch information like this
{ value:
[ { address: 'xxx#gmail.com', name: 'NAME' } ],
html:
'NAME <xxx#gmail.com>',
text: 'NAME ' }
I would like to know how to fetch email and name separately.
I have tried console.log(mail.from.address) or (mail.from.mailto) but it returns undefined

try
mail.from.value[0].address // fetch email
mail.from.value[0].name //fetch name

Related

How do I get all entries with a value in mySql then loop through foreach

I am wanting to send a message to the discord id(VERIFICATIONLINK), I know how to send messages with ids, but I am wanting to find out how I can loop through every entry that has 'VERIFIED'=InProgress, get the other values in that entry to use in the foreach loop.
The image is how the mysql table look right nowenter image description here
The below code is what I have in the connected to mysql part right now
host: config.mysqlhost,
port: config.mysqlport,
user: config.mysqluser,
password: config.mysqlpassword,
database: config.mysqldatabase,
})
connection.connect(err => {
if(err) throw err;
console.log("Connected to db")
})
client.connection = connection;
function continueVerification(){
let Playervals = connection.query("SELECT * FROM " + config.mysqltable + " WHERE VERIFIED='InProgress'", console.log);
//take that above info and loop into foreach
//in the foreach, I will send a message to each entry via the 'LINKVERIFICATION' entry which is their discordID
}```
You do it like this:
function continueVerification() {
connection.query("SELECT * FROM " + config.mysqltable + " WHERE VERIFIED='InProgress'", (err, rows) => {
rows.forEach(row => {
/// our code
})
})
}
Or if you want to const value of mysql select result you need use promise for this, because mysql.query is a callback function.
const Playervals = await getVerifiedUsers()
const getVerifiedUsers = () => {
return new Promise(resolve => {
connection.query("SELECT * FROM " + config.mysqltable + " WHERE VERIFIED='InProgress'", (err, rows) => {
resolve(rows)
})
})
}

Nodejs Request values

So I have a nodejs server and I am trying to make comparisons to the req values. Firstly, here is my code:
app.post('/', function(req, res) {
firstName = req.body.firstName;
lastName = req.body.lastName;
message = req.body.message;
token = req.body.token;
user = {name: firstName + " " + lastName, token: token};
selectedUser = req.body.selectedUser;
users.push(user);
console.log(user.name);
if (req.body.isAndroid === true) {
sendToAndroid(); //add message parameter
} else {
sendToios(); //add message parameter
}
});
app.listen(8080, function() {
console.log('running on port 8080');
});
//GCM
function sendToAndroid() {
var message = new gcm.Message();
var tokenLocation;
//API Server Key
var sender = new gcm.Sender('AIzaSyD-B3EG1xpMh6YhwBKfLMyw0GIQKWfGgZM');
//console.log(message);
// Value the payload data to send...
message.addData({
title: 'Hello',
body: 'Message From: ' + user.name + ': ' + message,
msgcnt: 1,
timeToLive: 3000
});
// At least one reg id required
if (registrationToken.indexOf(token) == -1) {
registrationToken.push(token);
tokenLocation = registrationToken.indexOf(token);
} else {
tokenLocation = registrationToken.indexOf(token);
}
if (users.indexOf(user.name) == -1) {
console.log("user destination not found");
} else {
var userTokenArray = [];
userTokenArray.push(user.token);
sender.send(message, { registrationTokens: userTokenArray } , function (err, response) {
if(err) console.error(err);
else console.log(response);
});
userTokenArray.pop();
}
}
And here is my problem when outputting to see what the value is:
running on port 8080
undefined undefined
user destination not found
What I am trying to do is put the registered users into an array of users that each element has a full name and token. Then in the Android function, it will check to see what value value is selected and then push a notification to the selectedUser via their token. I am so confused on how to compare the "strings" or whatever they are. I am using nodejs express with body-parser.

NodeJs handling the multiple mysql requests

I am new to nodejs and I am trying to use multiple queries to display result in a single page. I have used async parallel to get the result but I am unable to handle the requests.
This is my callback function
gettournamentDetail: function (res, req) {
var connection = mysqlConnectionProvider.getSqlConnection();
//var test=[];
var collection = { collection:[] };
var sqlStatement = "SELECT * FROM tournaments WHERE tournamentId =" + res;
var tgroup1 = { collection:[]};
var tournamentdetails = [];
var sqlStatement2 = "select * from " +
"(SELECT DISTINCT teamId, teamName,ttournament FROM teams, tournamentTeam WHERE ttournament=" + res + ") as main LEFT JOIN (SELECT DISTINCT groupName,groupTournament FROM groupTeam,tournamentGroup WHERE groupt=tgId) as sub ON sub.groupTournament=main.ttournament";
// var return_data = {};
async.parallel([
function () {
if (connection) {
connection.query(sqlStatement, function (err, rows, fields) {
rows.forEach(function (row) {
tournamentdetails=row;
});
req(tournamentdetails);
});
}
},
function () {
var tgroup=[];
if (connection) {
connection.query(sqlStatement2, function (err, rows, fields) {
for (var i in rows) {
tgroup.push("group",{
teamName: rows[i].teamName,
teamId: rows[i].teamId,
groupName: rows[i].groupName
});
}
req(tgroup);
});
}
}
This is my routing page
exports.tournamentDetail = function( req, res) {
var tournamentdetail = require('../database/getTournament.js');
tournamentdetail.tournament.gettournamentDetail(req.params.id, function (collection) {
console.log(collection);
//res.render('tournamentdetail', {title: 'Tournament Detail ', tdetail: collection});
});
};
Any Idea how Can I handle the two requests to display the data.
This is how I am getting the data
RowDataPacket {
tournamentId: 1,
tournamentUser: 1,
tournamentDate: 1472299200,
tournamentLocation: 'Reading',
tournamentDesc: 'An alternative to renaming app.js is to create an elastic beanstalk configuration file. Add a .config file into the .ebextensions folder, for example, .ebextensions/34.config. Change the NodeCommand setting in the namespace aws:elasticbeanstalk:container:nodejs to whatever command you want to run to start the server. For example, this is a minimal .config file to run npm start instead of app.js:\n\n',
tournamentInfo: 'Test',
tournamentCreated: 1471171131,
tournamentName: 'Ping Pong' }
[ 'group',
{ teamName: 'TeamName', teamId: 1, groupName: 'A' },
'group',
{ teamName: 'Team2', teamId: 2, groupName: 'A' } ]
I little simplify you code, but I don't understand exactly what you needs.
// connect on application start
var connection = mysqlConnectionProvider.getSqlConnection();
if (!connection)
throw new Error('Smth wrong');
...
let getTournamentDetail = function (tournament_id, callback) {
// I think both queries are bad, because they used Cartesian product and distinct
// Use placeholder to escaping params; it's more safety
var sql = 'select * from tournaments where tournamentId = ??';
var sql2 = 'select distinct teamId, teamName, ttournament '+
'from teams, tournamentTeam WHERE ttournament = ??) as main ' +
'left join (select distinct groupName, groupTournament ' +
'from groupTeam, tournamentGroup where groupt = tgId) as sub ' +
'on sub.groupTournament = main.ttournament';
async.parallel([
function (callback) { connection.query(sql, [tournament_id], callback) },
function (callback) { connection.query(sql2, [tournament_id], callback) }
],
function (err, results) {
if (err)
return callback(err);
callback(null, {tournamentdetails: results[0], tgrup: results[1]})
}
);
}
...
var youRouteFunc = function (req, res) {
getTournamentDetail(req.params.id, function (err, data) {
if (err)
return res.send(err.message);
res.render('tournamentdetail', {title: 'Tournament Detail ', tdetail: data});
});
}

NodeJs Store Json from multiple requests to MySQL DB

I am working on a crawler that stores the retrieved and parsed data into my MySQL DB.
Storing the results works pretty well, but I am stuck when it comes to end the connection.
I am using request, cheerio, async and mysql:
// DB params
var con = mysql.createConnection({
host: "localhost",
user: "user",
password: "password",
database: "mydatabase",
});
// Open connection to DB
con.connect(function(err) {
if (err) {
console.log('Error connecting to Db');
return;
}
console.log('Connection established');
});
// Array of Cities to crawl
var cities = ["olten", "zurich"];
// Todays Date
var today = new Date();
...
today = dd + '.' + mm + '.' + yyyy;
// Search every city
async.each(cities, function(item, callback){
// The Page to crawl
var page = "https://www.thepageto.com/search_xhr?fn=" + /*cities[i]*/ item + "&tn=&db=" + today + "&sort=trip_date&order";
console.log("Visiting page " + page);
request(page, function(error, response, body) {
if (error) {console.log("Error: " + error);}
// Check status code (200 is HTTP OK)
console.log("Status code: " + response.statusCode);
if (response.statusCode === 200) {
// Parse JSON
var data = JSON.parse(body);
// Use only result > html code
var content = data.html.results;
// Parse html
var $ = cheerio.load(content);
// Iterate through offers & Extract information & Store in a Object
$('.trip.relative').each(function() {
// Empty Object, has the same structure as the Db table
var json = {id: "", driver: "", rating: "", date: "", time: "", start: "", stops: "", end: "", price: "", url: "", query: ""};
// Assigning values
json.driver = $(this).find('.username').text();
...
// Save filled object in Db
save(json, callback);
});
}
});
}, function(err){
if (err) {
console.log('could not save');
} else {
console.log('lets end connection');
con.end(function(err) {if (err) throw err;});
}
}
);
function save(item, callback) {
con.query('INSERT INTO offers SET ?', item, callback);
}
The problem is, that the DB connection is ended before anything could be stored into the DB. The con.end() is always fired before the actual query or before the query completed. I have the intension that the save function has to return something when its done. If i run the script without the con.end(), the data is stored into the DB perfectly.
I am new to Node so I am still learning and hopefully you can help me with this.
Edit:
I now get an:
ReferenceError: callback is not defined
at save (/home/juki/crawler/crawler.js:143:46)
As well as an:
Error: Callback was already called.
at Query._callback (/home/juki/crawler/node_modules/async/dist/async.js:839: 36)
It looks like you do not call callback from your crawler.
You also do not seem to wait for save to finish. Try to rework save function, so it takes callback too. Something like:
function save(item, callback) {
con.query('INSERT INTO offers SET ?', item, callback);
}
And then call it like:
save(json, callback);
where callback is the one you get from async.each.

Node.js mysql transaction

Can anyone provide an example of how I could achieve MySQL transactions in Node.js. I am trying to get my head around using the node-mysql driver and node-mysql-queue.
As far are I can tell, using node-mysql-queue greatly reduces the asynchronous nature of Node.js as new queries have to wait until existing ones have completed. To get around this, has anyone attempted to combine node-mysql-queue with node-mysql's connection-pooling capabilities. i.e starting a new mysql connection for each new http request, and starting transaction queues on individual connections?
Update
See the edit below for async/await syntax
I spent some time writing a generalized version of the transaction example given by node mysql, so I thought I would share it here. I am using Bluebird as my promise library, and used it to 'promisify' the connection object which simplified the asynchronous logic a lot.
const Promise = ('bluebird');
const mysql = ('mysql');
/**
* Run multiple queries on the database using a transaction. A list of SQL queries
* should be provided, along with a list of values to inject into the queries.
* #param {array} queries An array of mysql queries. These can contain `?`s
* which will be replaced with values in `queryValues`.
* #param {array} queryValues An array of arrays that is the same length as `queries`.
* Each array in `queryValues` should contain values to
* replace the `?`s in the corresponding query in `queries`.
* If a query has no `?`s, an empty array should be provided.
* #return {Promise} A Promise that is fulfilled with an array of the
* results of the passed in queries. The results in the
* returned array are at respective positions to the
* provided queries.
*/
function transaction(queries, queryValues) {
if (queries.length !== queryValues.length) {
return Promise.reject(
'Number of provided queries did not match the number of provided query values arrays'
)
}
const connection = mysql.createConnection(databaseConfigs);
Promise.promisifyAll(connection);
return connection.connectAsync()
.then(connection.beginTransactionAsync())
.then(() => {
const queryPromises = [];
queries.forEach((query, index) => {
queryPromises.push(connection.queryAsync(query, queryValues[index]));
});
return Promise.all(queryPromises);
})
.then(results => {
return connection.commitAsync()
.then(connection.endAsync())
.then(() => {
return results;
});
})
.catch(err => {
return connection.rollbackAsync()
.then(connection.endAsync())
.then(() => {
return Promise.reject(err);
});
});
}
If you wanted to use pooling as you suggested in the question, you could easily switch the createConnection line with myPool.getConnection(...), and switch the connection.end lines with connection.release().
Edit
I made another iteration of the code using the mysql2 library (same api as mysql but with promise support) and the new async/await operators. Here is that
const mysql = require('mysql2/promise')
/** See documentation from original answer */
async function transaction(queries, queryValues) {
if (queries.length !== queryValues.length) {
return Promise.reject(
'Number of provided queries did not match the number of provided query values arrays'
)
}
const connection = await mysql.createConnection(databaseConfigs)
try {
await connection.beginTransaction()
const queryPromises = []
queries.forEach((query, index) => {
queryPromises.push(connection.query(query, queryValues[index]))
})
const results = await Promise.all(queryPromises)
await connection.commit()
await connection.end()
return results
} catch (err) {
await connection.rollback()
await connection.end()
return Promise.reject(err)
}
}
The following transaction example was added to the documentation a month ago:
https://github.com/felixge/node-mysql#transactions
connection.beginTransaction(function(err) {
if (err) { throw err; }
connection.query('INSERT INTO posts SET title=?', title, function(err, result) {
if (err) {
connection.rollback(function() {
throw err;
});
}
var log = 'Post ' + result.insertId + ' added';
connection.query('INSERT INTO log SET data=?', log, function(err, result) {
if (err) {
connection.rollback(function() {
throw err;
});
}
connection.commit(function(err) {
if (err) {
connection.rollback(function() {
throw err;
});
}
console.log('success!');
});
});
});
});
I am using the following approach. There is an add function in my Model where I am performing database operations.
add : function (data, callback) {
//Begin transaction
connection.beginTransaction(function(err) {
if (err) {
throw err;
}
var user_query = "INSERT INTO `calldata`.`users` (`username`, `password`, `enabled`, `accountNonExpired`, `accountNonLocked`, `credentialsNonExpired`) VALUES ('" + data.mobile + "', '" + sha1(data.password) + "', '1', '1', '1', '1')";
connection.query(user_query, function(err, results) {
if (err) {
return connection.rollback(function() {
throw err;
});
}
var accnt_dtls_query = "INSERT INTO `calldata`.`accnt_dtls` (`req_mob_nmbr`, `usr_nme`, `dvce_id`, `mngr_id`, `cmpny_id`, `actve_flg`, `crtd_on`, `usr`) VALUES (" + data.mobile + ", '" + data.name + "', '', " + data.managerId + ", " + data.companyId + ", 1, now(), '" + data.mobile+ "')";
connection.query(accnt_dtls_query, function(err, results) {
if (err) {
return connection.rollback(function() {
throw err;
});
}
var user_role_query = "INSERT INTO `calldata`.`user_roles` (`username`, `ROLE`) VALUES ('" + data.mobile + "', '" + data.role + "')";
connection.query(user_role_query, function(err, result) {
if (err) {
return connection.rollback(function() {
throw err;
});
}
//add an entry to manager table
var mngr_dtls_query = "INSERT INTO `calldata`.`mngr_dtls` (`mngr_nm`, `cmpny_id`, `crtd_on`, `usr_nm`, `eml_id`) VALUES ('" + data.name + "'," + data.companyId + " , now(), '" + data.mobile + "', '" + data.mobile + "')";
connection.query(mngr_dtls_query, function(err, result) {
if (err) {
return connection.rollback(function () {
throw err;
});
}
console.log('Changed ' + result.changedRows + ' results');
connection.commit(function (err) {
console.log('Commiting transaction.....');
if (err) {
return connection.rollback(function () {
throw err;
});
}
console.log('Transaction Complete.');
connection.end();
callback(null, result);
});
});
});
});
});
});
//transaction ends here
}
and calling from controller:
agentAccountModel.add(data, function(err, results) {
if(err)
{
res.status(500);
res.json({
"status": 500,
"message": err
});
}
res.status(200);
res.json({
"status": 200,
"message": "Saved successfully"
});
});
I have come up with a solution using a recursive function.
var sql = 'INSERT INTO logs SET data = ?';
// array of rows to insert
var rows = [[/*first row*/], [/*additional row*/]];
connection.beginTransaction(function (err) {
if (err) {
throw err;
}
var insertEachRow = function () {
var row = rows.shift();
if (! row) {
// Done, now commit
return noMoreRows();
}
connection.query(sql, row, function (err, result) {
if (err) {
connection.rollback(function () {
throw err;
});
}
insertEachRow();
});
};
var noMoreRows = function () {
connection.commit(function (err) {
if (err) {
connection.rollback(function () {
throw err;
});
}
console.log('success!');
});
};
insertEachRow();
});
I found one useful links which uses node js mysql pooling with transaction. Database Connection pooling is always useful. One can check this link
https://github.com/mysqljs/mysql
I created a wrapper ORM type thing for this specific purpose, hope it helps SQl-connecton - pool ORM type helper methods
You can use it with the mysql also, just use this function without any parameters /call back .
Make sure you have async function and use these instead
await con.rollback();
await con.beginTransaction();
await con.commit();
Life set.....