Run Sequelize raw query for each result of another sequelize query - node.js

i am using sequelize.js in node app to fetch data from a query and then run another sequelize raw query for each result element. but dude to callbacks i am not getting results.
my code:
var raw_query1 = "select id,name,has_results from users";
sequelize.query(raw_query1).then(function(results) {
var outputArray = []; // to store use results with additional results
for(i=0;i<results.length;i++){
outputArray[i].name = results[i].name;
var raw_query2 = "select * from meta where user_id = "+resulsts[i].id;
sequelize.query(raw_query2).then(function(meta_results) {
outputArray[i].meta = meta_results;
}
}
return res.json(outputArray); //Returning parsed results
});
i think we need to use promise here but i am a newbie from php and dont know how to proceed thanks in advance.

You need to use bluebird.map.
var raw_query1 = "select id,name,has_results from users";
sequelize.query(raw_query1).then(function(results) {
return bluebird.map(results, function(user){
var raw_query2 = "select * from meta where user_id = "+user.id;
return sequelize.query(raw_query2)
})
.then(function(metas){
return res.json(metas);
});
});

Related

Building a kitchen sink query. Error passing # parameters to SQL Server

Im building a kitchen sink query on NODE, where several parameters, for about 20 tables are being passed. They all form a single SQL Query:
if (data.basics.memberId) { sqlString += ` memberid=#memberId and` };
etc...
Im passing several parameters (about 40), but Im not able to pass the parameters when sending the query to the database:
const pool = await utils.poolPromise
const recordset = await pool.request()
//basics
if (data.basics.memberId) {
.input('memberId', utils.sql.Int, data.basics.memberId)
};
.query(sqlString)
if (recordset.rowsAffected[0] > 0) {
...
...
...
}
and Im getting the error:
Declaration or statement expected.
at
.input('memberId', utils.sql.Int, data.basics.memberId)
and
.query(sqlString)
I've read parameters are not the right way to build dynamic queries, so I thought of using ES6, as
if (data.basics.memberId) { sqlString += ` memberid=${data.basics.memberId} and` };
But I've read that ES6 does not prevent SQL injection on SQL Server.
The question is how do I approach this scenario where the SQL string is variable and changes based on the user selection?
Thanks.
Without a query builder library (e.g. Knex), you'll need to
form the SQL query (as a string)
put the parameters into place
e.g. something like this:
const whereClauses = [];
const inputs = {}; // map input name -> [type, value]
// (1) Process data into WHERE clauses and inputs
if (data.basics.memberId) {
whereClauses.push(`memberid=#memberId`);
inputs.memberId = [utils.sql.Int, data.basics.memberId];
}
if (data.basics.somethingElse) {
whereClauses.push(`somethingElse=#somethingElse`);
inputs.somethingElse = [utils.sql.Int, data.basics.somethingElse];
}
// (etc..., you could use a loop or something for the above)
// (2) Form the final SQL query
const sqlStringBits = ["SELECT * FROM ... WHERE "];
for (let whereClause of whereClauses) {
sqlStringBits.push(whereClause);
sqlStringBits.push("AND");
}
if (whereClauses.length) {
sqlStringBits.pop(); // Remove final AND if we had added one
}
const sqlString = sqlStringBits.join(" ");
// (3) Form the `request` and put the inputs into place
const pool = await utils.poolPromise;
let request = pool.request();
for (let inputName in inputs) {
request = request.input(inputName, ...inputs[inputName]);
}
// (4) Use the request (endowed with inputs) with the query
const recordSet = await request.query(sqlString);
// (5) Do something with the record set!

Array as sql request parameter

I handle my SQL queries like this (which works):
const sql = require("mssql/msnodesqlv8");
const conn = new sql.ConnectionPool({
database: "MyDatabase",
server: "localhost\\SQLEXPRESS",
driver: "msnodesqlv8",
options: {
trustedConnection: true
}
});
async function runSQLQuery(insertReq, query) {
try {
await conn.connect();
var result = await insertReq.query(query);
await conn.close();
return result;
} catch (ex) {
console.log(ex);
return undefined;
} finally {
if (conn.connected)
conn.close();
}
}
and create the querys like this (which also works):
exports.getClientByID = async function (ID) {
var insertReq = conn.request();
insertReq.input("ID", sql.UniqueIdentifier, ID);
const request = await runSQLQuery(insertReq, `SELECT TOP (1) * FROM ${ClientTabel} WHERE ID = #ID`);
return request.recordset[0]
};
But now I want to add an Array as Parameter like this (and this doesn't work):
exports.getUsersWithProperty = async function (properties) {
var insertReq = conn.request();
insertReq.input("properties", sql.NVarChar, properties);
const request = await runSQLQuery(insertReq, `SELECT * FROM ${ClientTabel} WHERE Property IN #properties`);
return request.recordset;
};
But with this I only get a
Request Error" Wrong Syntax near "#properties".
I guess the type sql.NVarChar is wrong but I don't know what the right type is. Whats the solution for this?
OK, for a start, you need to add brackets around the values.
An IN clause is like this:
WHERE somecolumn IN ('value1','value2','value3')
you'll also have to make sure that after your #properties string replacement is done, you end up with a statement that looks like the clause above, with the quotes and commas in the right places.
Alternately, if #properties is a string like Value1,Value2,Value3 and so on, you could pass it to a T-SQL table-valued function that returns a table like this:
WHERE somecolumn IN dbo.ExtractStringList(#StringList)

How to destructure multiple query results in sequence?

I want to use the same pattern for destructuring query results, but seems I cannot. In the following code:
var {rows} = await client.query("SELECT id FROM mytable;");
var Id = rows[0].id; //destructured here as expected
if I then follow that with:
rows = await client.query('SELECT max(id) as id FROM table2;');
The only way I can access the value is like this:
rows.rows[0].id;
Shouldn't I be able to access as in the first instance, like this?
rows[0].id;
Do I need to somehow reset {rows}?
Very new to JS so finding my way.
You still need to restructure the variable. Simply assign to rows will just get the full response object assigned to the variable, as you've seen.
Destructuring to the same variable has a couple gotchas because you can't do this:
let {rows} = await client.query("SELECT id FROM mytable;");
// Error: unexpected token without declaration
{rows} = await client.query('SELECT max(id) as id FROM table2;');
// Error: Identifier 'rows' has already been declared
let {rows} = await client.query('SELECT max(id) as id FROM table2;');
You can declare var multiple times:
var {rows} = await client.query("SELECT id FROM mytable;");
// no problemo
var {rows} = await client.query('SELECT max(id) as id FROM table2;');
If you want to declare with let then you need to do something like:
let {rows} = await client.query("SELECT id FROM mytable;");
// this works too…
({rows} = await client.query('SELECT max(id) as id FROM table2;'));

How to set parameterized value in Postgres SELECT query using WHERE condition

I am very new to PostgreSQL please bear with me.
I need to read records from the table using select query with where condition.
Eg: select * from switch where switchId=10;
QueryFactory.js
let queryMap = {
“getSwitchInfo”: ‘select * from switch where switchId=?’
}
module.exports=queryMap;
Controller.js
let client = require(rootdir+’dao/postgresSQL’);
let queryFactory = require(rootdir+’/dao/QueryFactory’);
let query = queryFactory.getQuery(“getSwitchInfo”);
let switchId = req.query.switchId;
client.query(query, function(err, res){
if(err){
}
});
Please see:- this switchId value 10 I get from client and using query parameter I am getting it in my node backend layer.
Kindly suggest how can I pass switchId to the query as a parameterized value.
I found solution myself for this issue. Added params to an array and passed this array as a second param to client.query method and in the query where condition I added $1. It is working fine now
QueryFactory.js
let queryMap = {
“getSwitchInfo”: ‘select * from switch where switchId=$1’
}
module.exports=queryMap;
Controller.js
let params = [req.query.switchId];
client.query(query, params, function(err, res){
if(err){
}
});

Return from then - nodejs

I am sort of new to NodeJS and I'm learning as I code but I can't wrap my head around Promise/then.
Here is the piece of code - I'm using a library function to Read database values.
var collection = 'Students';
var query = {};
query.name = 'name';
//readFromDatabse returns -{Function} a promise to return the document found, or null if not found
var temp = readFromDatabase(collection, query).then(function(studentData) {
var result = {
resultDetails: {
username: studentData.username,
password: studentData.password
}
};
return callback(null,resultDetails);
});
but when I read see the values in temp, it contains {"isFulfilled":false,"isRejected":false}!! how can I get the result details into temp?
You have to think of Promises as containers for values. readFromDatabase returns such a container, which might eventually hold the requested value unless the query fails. Your temp variable points to the container, but not the response. The properties isFullfilled and isRejected are attributes of the Promise telling you that it has neither been resolved with a value or rejected with an error.
To get to the response you have to use the then method. The function you register there will be called for you, when the query yields a result or an error.
var collection = 'Students';
var query = {};
query.name = 'name';
var temp = null;
readFromDatabase(collection, query).then(function(studentData) {
var result = {
resultDetails: {
username: studentData.username,
password: studentData.password
}
};
temp = result;
});
// temp is still null here

Resources