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
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;
}
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).
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
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.
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