How i can execute multiple queries (UPDATE) in NODE using Sequelize? - mysql

I need to execute multiples queries in NODE using Sequelize.
I tried execute with a for, but it's didn't work.
Someone can help me?
exports.update = async (req, res) => {
for (let i = 0; i < req.body.length; i++) {
const id = req.body[i].id;
const permissao = req.body[i].permissao;
const sql =
`UPDATE tetsiste_usuarios.usuarioGraficos SET permissao = ${permissao} \n
WHERE id = ${id} AND permissao <> ${permissao};`;
sequelize.query(sql, { type: Sequelize.QueryTypes.UPDATE })
.then(data => res.json(data))
}
}

You need to await the call the sequelize.query but that said... you are doing this all wrong. The idea behind using an ORM like Sequelize is that it abstracts the SQL and provides protection against things like SQL injection attacks and malormed queries, which your code is susceptible to. If I mess with the request and pass in this for permissao it will drop your database table 1; DROP TABLE usuarioGraficos; SELECT 1 FROM dual. That is bad. You're also calling res.json() on every loop, which will also result in an error.
The proper way to do this is to use the Model.create() function for inserts or Model.update() for updates.
loop insert with sql injection vulnerability
const Sequelize = require('sequelize');
const models = require('./models'); // your model definitions
// an array to store our results
const updates = [];
// use a forEach to get each entry from the body array
for (let i = 0; i < req.body.length; i++) {
// this ID
const id = req.body[i].id;
// this permission
const permissao = req.body[i].permissao;
// update the permission where the ID matches and the permission does not
const update = await models.UsuarioGraficos.update({ permissao }, {
where: {
id,
permissao: {
[Sequelize.Op.ne]: permissao,
},
},
});
// add the result
updates.push(update);
}
// send all the updates outside the loop
res.json(updates);

Related

Node.js trying to use async/await to get data from a mysql select before using the variable

I need to catch some data by a mysql query, and use the result to build up and email message with its results with node.
I put the code inside a function, but the call to the query appear to still be async, as the result is never given back before the end of the function, and the returning variable is alwasy empty.
Tried different approach with async/await but still the execution seems async
In my following code is just get in the console log up to the step 3, the step 4 is mde no matter what I try to do at the end of the function call
async function querydb (utente){
console.log("sono in querydb");
var messageHTMLAllegati="";
var risultatoquery;
console.log("step 1");
var connection = mysql.createConnection({
host : process.env.IP_address,
user : process.env.nome_utente,
password : process.env.password,
port : process.env.port,
database : process.env.DB,
});
console.log("step 2");
const query = util.promisify(connection.query).bind(connection);
(async () => {
try {
console.log("step 3");
var result = await query('SELECT Link FROM Link_Foto where ID_Utente="' + utente + '"');
var i = result.length;
console.log("step 4");
var j ;
for (j=0; j < i; j++) {
messageHTMLAllegati +='Immagine ' + (j+1)+ '<BR>';
console.log("print the link found in the DB and added to the text to be printed"+result[j].Link);
}
} finally {
connection.end();
}
})()
return messageHTMLAllegati;
}
I do expect the final variable "messageHTMLAllegati" to contain some text plus the query fields needed, but it get always empty. In the log I see though that the variable is filled up, but only after that the function is returned, therefore the text used to put the email together is empty from the DB section
async/await method only works when await functions is a promise. functions like 'query' in mysql are using a callback function to get the result. So if you want to use it with async/await method you should use it in another function and get the result in its callback function as a promise like this:
function query_promise(q_string){
return new Promise((resolve, reject)=>{
query(q_string,(err, result)=>{
if(err) return reject(err);
resolve(result);
});
});
}
then in your code:
var result = await query_promise('SELECT Link FROM Link_Foto where ID_Utente="' + utente + '"');

firebase cloud functions limit children

Thank you I am deploying a function to limit the child nodes generated from push command.The link I am following code to limit child node Now I am just editing this code putting my custom code as follows link:
'use strict';
const functions = require('firebase-functions');
// Max number of lines of the chat history.
const MAX_LOG_COUNT = 1;
// Removes siblings of the node that element that triggered the function if there are more than MAX_LOG_COUNT.
// In this example we'll keep the max number of chat message history to MAX_LOG_COUNT.
exports.truncate = functions.database.ref('/grid/{pushId}').onWrite((change) => {
const parentRef = change.after.ref.parent;
return parentRef.once('value').then((snapshot) => {
if (snapshot.numChildren() >= MAX_LOG_COUNT) {
let childCount = 0;
const updates = {};
snapshot.forEach((child) => {
if (++childCount <= snapshot.numChildren() - MAX_LOG_COUNT) {
updates[child.key] = null;
}
});
// Update the parent. This effectively removes the extra children.
return parentRef.update(updates);
}
return null;
});
});
So here I deploy the functions to limit the children but, getting error in firebase logs as:
TypeError: Cannot read property 'ref' of undefined
at exports.truncate.functions.database.ref.onWrite (/user_code/index.js:11:33)
at Object.<anonymous> (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:59:27)
at next (native)
at /user_code/node_modules/firebase-functions/lib/cloud-functions.js:28:71
at __awaiter (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:24:12)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:53:36)
at /var/tmp/worker/worker.js:700:26
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
Not sure if you still need this. Have you initialized Firebase App? Add the following lines, if not already added, and check again.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
//Define your trigger

Call sql query synchrously

Currently working on node rest api project where I want to fetch data for a list of data. for example : I have a list of post_id([1,2,3....]) for a particular tag(mobile) and for each post_id I want to retrieve post title and description from mysql database. But calling sql query is synchrounous.
How to control flow for each post id result to combine in one.
my db calling code is here :
var express = require('express');
var app = express();
var bodyParser = require('body-parser'); // call body-parser
var addData = require('./dbhandler/addData'); // call database handler to insertdata
var getData = require('./dbhandler/getData');
//route function to get feeds by tags
router.route('/postfeedsbytags/:tag')
// get all new article feeds filtered by tag
.get(function(req,res){
var success;
console.log(req.params.tag)
var json_results = [];
getData.getPostFeedsByTag(req.params.tag,function(error, results, fields){
if (!error){
for (var i = 0; i < results.length; i++) {
getData.getPostFeedsByPostId(results[0]['post_id'],function(error, results, fields){
if (!error){
success = 1;
json_results.push(results[0]);
res.json({"success" : success, "datasets" : json_results});
} else{
success = 0;
console.log('Error while performing Query.'+error);
res.json({"success" : success});
}
});
}
// res.json({"success" : success, "datasets" : results});
} else{
success = 0;
console.log('Error while performing Query.'+error);
res.json({"success" : success});
}
});
});
I think you can use the IN operator in the query to get all the posts in a single query and then iterate over it.
If you don't want to use IN operator then use async library for flow control. You can use the async.map function from it.

NodeJS - For loop - Wait for a callback to continue

I am trying to query, foreach id in an array, some data from the MySQL database.
My for loop looks like the following
for(var i = 0; i < res.length; i++) {
var steamid = res[i].steamid;
db.query('SELECT `name` FROM `users` WHERE `steamid`=?', [steamid], function(err, rows) {
var player = {name: rows[i].name};
team.push(player);
});
}
But the problem is that the for loop continues before the query is finished and then the var i is already increased by one or two.
Is there a way to check if the query has finished?
Just use a closure so that your i refers to the correct index.
function finished(){...}//called when you fetched all your data
var nbDone = 0;
res.forEach(function(elem, i){
var steamid = elem.steamid;
db.query('SELECT `name` FROM `users` WHERE `steamid`=?', [steamid], function(err, rows) {
var player = {name: rows[i].name};
team.push(player);
nbDone++;
if(nbDone == res.length){
finished();//you know all of your queries have completed
}
});
});
you may want to have a look at promises or async in order to handle your asynchronous flows

Using Q to return secondary query in node with express and mysql

New to node, As I am cycling through a roster of students, I need to check and see if a teacher has requested them for tutoring.
I realized I can't just do this:
var checkRequest = function(id){
var value = '';
roster.query('SELECT * FROM teacher_request WHERE student_id ='+id, function(err, row){
value = row.length;
}
return value;
}
After a bit of digging around promises looked like a great solution, but if I simply return the deferred.promise from the checkRequest function, all I get is an object that says [deferred promise] which I can't access the actual data from. (Or have not figured out how yet)
If I follow along with their api and use .then (as illustrated in the getRow) function, I am back in the same problem I was in before.
function checkRequest(id) {
console.log(id);
var deferred = Q.defer();
connection.query('SELECT * FROM teacher_request WHERE student_id ='+id, function(err, row){
deferred.resolve(row.length);
});
return deferred.promise;
}
var getRow = function(id){
checkRequest(id).then(function(val) {
console.log(val); // works great
return val; //back to the same problem
});
}
The roster needs to be able to be pulled from an external API which is why I am not bundling the request check with the original roster query.
Thanks in advance
From the stuff you posted, I assume you have not really understood the concept of promises. They allow you to queue up callbacks, that get executed, when the asynchronous operation has finished (by succeeding or failing).
So instead of somehow getting the results back to your synchronous workflow, you should convert that workflow to work asynchronous as well. So a small example for your current problem:
// your students' ids in here
var studentsArray = [ 1, 2, 5, 6, 9 ];
for( var i=0; i<studentsArray.length; i++ ) {
checkRequest( i )
.then( function( data ){
console.log( data.student_id );
// any other code related to a specific student in here
});
}
or another option, if you need all students' data at the same time:
// your students' ids in here
var studentsArray = [ 1, 2, 5, 6, 9 ];
// collect all promises
var reqs = [];
for( var i=0; i<studentsArray.length; i++ ) {
reqs.push( checkRequest( i ) );
}
Q.all( reqs )
.then( function(){
// code in here
// use `arguments` to access data
});