Mysql + json formatting - mysql

In my node app i am using mysql. I retrieve data from mysql and converting each row to json(working fine).But my requirement i have to print the field with value otherwise don't.
Consider:
My sql result..
level0:"xxxxxx" level1:"fffffff" level3:"btggtgt" level:""
Now the json i am getting is:
[
{
level0="xxxxxxx",
level1="fffffff",
level3="btggtgt".
level4=""
}
]
But i need the output as:
[
{
level0="xxxxxxx",
level1="fffffff",
level3="btggtgt"
}
]
i have to omit level4 because its value is ""(empty).
My code is:
connection.query("select * from levels where level0 = '" + level0 + "' and level1 = '"+level1+"' and level2 = ''", function(err, row1, fields) {
res.writeHead(200, { 'Content-Type': 'application/json'});
res.end(JSON.stringify(row1,null,"\n"));
});
var query5result;
querylevel5(function(result5)
{
for (var level in result5)
{
console.log("ssssssss="+util.inspect(result5[level]))
if (result5[level] == null || result5[level] == '')
{
delete result5[level];
}
}
query5result=result5;

Here is a way to loop and delete this empty level
connection.query("select * from levels where level0 = '" + level0 + "' and level1 = '"+level1+"' and level2 = ''", function(err, row1, fields) {
for (var level in row1)
{
if (row1[level] == null || row1[level] == "")
{
delete row1[level];
}
}
)};
//...then go on:
res.end(JSON.stringify(row1,null,"\n"));

Related

How to parse Telnyx JSON in Google Sheets

I am looking for a way to parse the JSON received from Telnyx (through a webhook) in a Google spreadsheet, using in cell formulas.
The ideal outcome is to having data from each line in a separate column (including lines with no data), with the correct heading.
JS would also be an option.
I've tried using FILTER and REGEXMATCH with some results, but I couldn't manage to get a decent output.
Any help would be greatly appreciated.
The data received from Telnyx looks like this:
"{
""data"": {
""event_type"": ""message.received"",
""id"": ""0d9c22"",
""occurred_at"": ""2022-07-23T04:52:08.642+00:00"",
""payload"": {
""cc"": [],
""completed_at"": null,
""cost"": null,
""direction"": ""inbound"",
""encoding"": ""GSM-7"",
""errors"": [],
""from"": {
""carrier"": """",
""line_type"": """",
""phone_number"": ""+447""
},
""id"": ""eb17"",
""media"": [],
""messaging_profile_id"": ""4001"",
""organization_id"": ""8ab"",
""parts"": 2,
""received_at"": ""2022-07-20T04:52:08.464+00:00"",
""record_type"": ""message"",
""sent_at"": null,
""subject"": """",
""tags"": [],
""text"": ""SMS goes here.\nThanks"",
""to"": [
{
""carrier"": ""Telnyx"",
""line_type"": ""Wireless"",
""phone_number"": ""+447"",
""status"": ""webhook_delivered""
}
],
""type"": ""SMS"",
""valid_until"": null,
""webhook_failover_url"": null,
""webhook_url"": ""https://script.google.com/XXXXX""
},
""record_type"": ""event""
},
""meta"": {
""attempt"": 1,
""delivered_to"": ""https://script.google.com/""
}
}"
Try this recursive function (A1 contains the data)
=functionTelnyx(A1)
put in your script editor
function functionTelnyx(json) {
const telnyx = JSON.parse(json.slice(1,-1).replace(/""/g,'"').replace(/(\r\n|\n|\r|\t| )/gm, ""))
let result = [];
recursion(telnyx)
function recursion(obj, path) {
if (path == undefined) { path = 'telnyx' }
const regex = new RegExp('[^0-9]+');
for (let p in obj) {
let newPath = (regex.test(p)) ? path + '.' + p : path + '[' + p + ']';
if (obj[p] != null) {
if (typeof obj[p] != 'object' && typeof obj[p] != 'function') {
result.push([ p, obj[p]]);
}
if (typeof obj[p] == 'object') {
recursion(obj[p], newPath);
}
}
}
}
return result
}
edit:
for multiple json, and horizontal layout
for headers, put in B1 =telnyx_headers(A2)
for contents, put in B2 and drag below =telnyx_contents(A2), then =telnyx_contents(A3) and so forth
with
function telnyx_headers(json) {
const telnyx = JSON.parse(json.slice(1, -1).replace(/""/g, '"').replace(/(\r\n|\n|\r|\t| )/gm, ""))
let result = [];
recursion(telnyx)
function recursion(obj, path) {
if (path == undefined) { path = 'telnyx' }
const regex = new RegExp('[^0-9]+');
for (let p in obj) {
let newPath = (regex.test(p)) ? path + '.' + p : path + '[' + p + ']';
if (obj[p] != null) {
if (typeof obj[p] != 'object' && typeof obj[p] != 'function') {
result.push(p);
}
if (typeof obj[p] == 'object') {
recursion(obj[p], newPath);
}
}
}
}
return [result]
}
function telnyx_contents(json) {
const telnyx = JSON.parse(json.slice(1, -1).replace(/""/g, '"').replace(/(\r\n|\n|\r|\t| )/gm, ""))
let result = [];
recursion(telnyx)
function recursion(obj, path) {
if (path == undefined) { path = 'telnyx' }
const regex = new RegExp('[^0-9]+');
for (let p in obj) {
let newPath = (regex.test(p)) ? path + '.' + p : path + '[' + p + ']';
if (obj[p] != null) {
if (typeof obj[p] != 'object' && typeof obj[p] != 'function') {
result.push(obj[p]);
}
if (typeof obj[p] == 'object') {
recursion(obj[p], newPath);
}
}
}
}
return [result]
}
optional: array-enabled version
To process a larger number of JSON strings in the column A2:A, use this formula:
=telnyx(A2:A)
The telnyx() function uses telnyx_headers() and telnyx_contents() while observing custom function best practices.
/**
* Converts one or more JSON strings to a horizontal table.
* Row 1 will show field names and subsequent rows the
* data in each field.
*
* #param {A2:A} json The JSON strings to convert to a table.
* #customfunction
*/
function telnyx(json) {
'use strict';
if (!Array.isArray(json)) {
json = [json];
}
json = json.flat();
let result = telnyx_headers(json[0]);
json.forEach(j => result = result.concat(j ? telnyx_contents(j) : [null]));
return result;
}

Calculated Fields with nestTables Option for MySQL Query in NodeJS

I'm using the 'nestTables' option in the code below to separate the data returned from an SQL query into their respective tables. I am also including a calculated field in my query that I would like to include in the primary table.
As an example, I am executing the following route:
router.route('/person/:personId').get(function(req,res){
var person_id = req.params.personId;
db.getConnection(function(err, connection) {
if (err) {
return res.status(503).send({ result: false, error: 'CONNECTION error: ' + err.code});
} else {
var sqlString='SELECT *, someField - 1 as calculated FROM person LEFT JOIN person_status ON person.id = person_status.person_id WHERE person.id = ' + person_id;
var options={sql:sqlString,nestTables:true};
connection.query(options, function(error, rows, fields) {
connection.release();
var nestingOptions = [
{tableName: 'person', pkey:'id'},
{tableName: 'person_status', pkey:'id', fkeys:[{table:'person',col:'person_id'}]}
];
if (error) {
return res.status(500).send({ result: false, error: 'QUERY ERROR: ' + error.code});
} else {
return res.status(200).send(rows);
}
});
}
});
});
and I am receiving the following JSON Response:
[
{
"person": {
"id": 1,
other person data . . .
"person_status": [
{
"id": 3,
other data . . .
}
]
},
"person_status": {
"id": 3,
other data . . .
},
"": {
"calculated": 0
}
}
]
Ideally, I would like to include the calculated field into the person subgroup as shown below:
[
{
"person": {
"id": 1,
"calculated": 0
other person data . . .
"person_status": [
{
"id": 3,
other data . . .
}
]
},
"person_status": {
"id": 3,
other data . . .
}
}
]
Is there any way that I can include the calculated field into the person table, or is there a better solution that fits this problem?
Thanks in advance!
I see two options to solve this, one dirty way using SQL:
var sqlString = 'SELECT *, someField - 1 as calculated FROM person WHERE person.id=?';
sqlString = 'SELECT * FROM (' + sqlString + ') as person';
sqlString += ' LEFT JOIN person_status ON person.id = person_status.person_id';
var options={sql:sqlString, nestTables:true};
connection.query(options, [person_id], function(error, rows, fields) {
and the obvious solution using js:
var sqlString = 'SELECT *, someField - 1 as calculated FROM person LEFT JOIN person_status ON person.id = person_status.person_id WHERE person.id=?';
var options = {sql:sqlString, nestTables:true};
connection.query(options, [person_id], function(error, rows, fields) {
rows.forEach(function(row) {
row.person.calculated = row[''].calculated;
delete row[''];
});
I don't think there is a more pleasant solution for this. I even checked if there is a possibility to trick the FieldPacket or RowDataPacket parser but didn't see a way to fake a table name (without monkey patching the mysql driver).

Make query after query with nodejs and sequelize

I want to make a query after another query in node.js with sequqlize. Second query iterate ower the first elements query result.
The code:
exports.index = function(req, res) {
sqldb.sequelize.query("select * from food", {type: sqldb.sequelize.QueryTypes.SELECT})
.then(function (food) {
for (var i = food.length; i--;) {
sqldb.sequelize.query("select i.name_ingredient " +
"from food_incredients as fi, " +
"ingredients as i " +
"where fi.food_id = " + food[i].id + " and " +
"i.id = fi.ingredient_id;",
{type: sqldb.sequelize.QueryTypes.SELECT}).then(function (ingredients) {
food[i]["ingredients"] = ingredients;
});
}
res.status(200).json(food);
}
);
At the line when I try to add "infredients" field I reveive an error that the "food[i]" object is undefined. How can I fix this problem and return the "food" with ingredients for every elements?
Thanks

NodeJS - MySQL query error

My query works fine if the person exist in my table, but if he/she does not; the NodeJS will give me an error.
function ClientConnected(remoteClient)
{
debugLog(remoteClient.name + " connected to the server. (ID: " + remoteClient.networkId + ") Loading player data..");
sql.query('SELECT * FROM `players` WHERE `character_name` = ?', [remoteClient.name], function(err, rows)
{
if(err)
{
debugLog('[DB] Error when loading ' + remoteClient.name + "'s (" + remoteClient.networkId + ') data: ' + err.code);
} else {
players[remoteClient.networkId] = {
'a_socialid' : rows[0].account_socialid,
'i_money' : rows[0].inventory_money,
};
debugLog("Successfully loaded " + remoteClient.name + "'s (" + remoteClient.networkId + ") data..");
}
});
}
events.Add("ClientConnected", ClientConnected);
If someone joins with the name that already exists in the table, it will load the players data:
But if not, it gives me an error. (TypeError, undefined, blabla)
You need to check that a record was returned. Maybe something like this:
if(err)
{
debugLog('[DB] Error when loading ' + remoteClient.name + "'s (" + remoteClient.networkId + ') data: ' + err.code);
} else if (rows.length === 0) {
debugLog('Nothing returned from database');
} else {
// ...
}
Presumably the err result would only give you feedback on the actual query, not the data it returns.

Error in node js while fetching records from mysql database

Routes:
exports.authenticate = function(req, res) {
//connection.connect();
var sql="SELECT * from users where username='"+req.body.user+"' and password='"+req.body.pass+"' LIMIT 1";
connection.query(sql, function(err, rows, fields) {
if (err) throw err;
//res.send('Your data is: ', rows);
var str="Hi, <b>"+rows[0].name+"</b> ("+rows[0].email+")";
sql="SELECT username,name from users ORDER BY name";
connection.query(sql, function(err, datarows, fields) {
if (err) throw err;
//res.send('Your data is: ', rows+' <br/> All Users are : ', datarows.length+"<a href='/'>Login</a>");
console.log(datarows);
res.render('home.jade', {title: 'Home',result:datarows});
/*---------------The above calling jade-----------------*/
});
//str+="<a href='/'>Login</a>";
//res.send(str);
//connection.end();
});
Jade:
extends layout
block content
//p #{result}
-var list=[ { username: 'rohankumar1524', name: 'Rohan Kumar' }]
each item, i in result
p test #{item.length}
each role,j in item
p #{role}
Output
test
rohankumar1524
Rohan Kumar
unusual output
function (parser, fieldPackets, typeCast, nestTables, connection) { var self = this; var next = function () { return self._typeCast(fieldPacket, parser, connection.config.timezone, connection.config.supportBigNumbers); }; for (var i = 0; i < fieldPackets.length; i++) { var fieldPacket = fieldPackets[i]; var value; if (typeof typeCast == "function") { value = typeCast.apply(connection, [ new Field({ packet: fieldPacket, parser: parser }), next ]); } else { value = (typeCast) ? this._typeCast(fieldPacket, parser, connection.config.timezone, connection.config.supportBigNumbers) : ( (fieldPacket.charsetNr === Charsets.BINARY) ? parser.parseLengthCodedBuffer() : parser.parseLengthCodedString() ); } if (typeof nestTables == "string" && nestTables.length) { this[fieldPacket.table + nestTables + fieldPacket.name] = value; } else if (nestTables) { this[fieldPacket.table] = this[fieldPacket.table] || {}; this[fieldPacket.table][fieldPacket.name] = value; } else { this[fieldPacket.name] = value; } } }
Also this
function (field, parser, timeZone, supportBigNumbers) { switch (field.type) { case Types.TIMESTAMP: case Types.DATE: case Types.DATETIME: case Types.NEWDATE: var dateString = parser.parseLengthCodedString(); if (dateString === null) { return null; } if (timeZone != 'local') { if (field.type === Types.DATE) { dateString += ' 00:00:00 ' + timeZone; } else { dateString += timeZone; } } return new Date(dateString); case Types.TINY: case Types.SHORT: case Types.LONG: case Types.INT24: case Types.YEAR: case Types.FLOAT: case Types.DOUBLE: case Types.LONGLONG: case Types.NEWDECIMAL: var numberString = parser.parseLengthCodedString(); return (numberString === null || (field.zeroFill && numberString[0] == "0")) ? numberString : ((supportBigNumbers && Number(numberString) > IEEE_754_BINARY_64_PRECISION) ? numberString : Number(numberString)); case Types.BIT: return parser.parseLengthCodedBuffer(); case Types.STRING: case Types.VAR_STRING: case Types.TINY_BLOB: case Types.MEDIUM_BLOB: case Types.LONG_BLOB: case Types.BLOB: return (field.charsetNr === Charsets.BINARY) ? parser.parseLengthCodedBuffer() : parser.parseLengthCodedString(); case Types.GEOMETRY: return parser.parseGeometryValue(); default: return parser.parseLengthCodedString(); } }
But when I use this code in jade
extends layout
block content
//p #{result}
-var list=[ { username: 'rohankumar1524', name: 'Rohan Kumar' }]
each item, i in list // list in place of result
p test #{item.length}
each role,j in item
p #{role}
The output is
test
rohankumar1524
Rohan Kumar
which is expected
Why this problem occurs, is any other module I have install by npm
Try this:
Jade
extends layout
block content
each item in result
p item.username
p item.name