I have a JSON Object and want to UPDATE a mySQL table, without List all of the Keys
with an INSERT I do this like
var arrayValue = Object.keys(obj).map(function(key) {
return String("'"+obj[key]+"'");
});
var arrayKeys = Object.keys(obj).map(function(key) {
return String(key);
});
var sql = "INSERT INTO `modules` "+ " (" +arrayKeys.join() + ") VALUES ("+arrayValue.join()+");";
con.query(sql, function (err, result, fields) {
if (err) throw err;
return result;
});
The same i would do with UPDATE
How can i do this?
does this fill your needs?
const object = {
id: 1,
firstName: "John",
lastName: "Doe"
};
const columns = Object.keys(object);
const values = Object.values(object);
let sql = "INSERT INTO tableName ('" + columns.join("','") +"') VALUES (";
for (let i = 0; i < values.length; i++) {
sql += "?";
if (i !== values.length - 1) {
sql += ",";
}
}
sql+= ")";
connection.query(sql, values, (error, result, fields) => {
//do what you must here.
});
For update:
const object = {
id: 1,
firstName: "John",
lastName: "Doe"
};
const columns = Object.keys(object);
const values = Object.values(object);
let sql = "UPDATE tableName SET '" + columns.join("' = ? ,'") +"' = ?";
connection.query(sql, values, (error, result, fields) => {
//do what you must here.
});
Off course what would you put in the where statement?
I hope this helped.
here the example
/ Update an existing user
app.put('/users/:id', (request, response) => {
const id = request.params.id;
pool.query('UPDATE users SET ? WHERE id = ?', [request.body, id], (error, result) => {
if (error) throw error;
response.send('User updated successfully.');
});
});
that works for me
Related
I am struggling with an incredibly weird issue with a function.
Here is the code that inserts the data:
const pi = async () => {
return new Promise((resolve) => {
db.query(
"SELECT classID FROM pacesetterIndex WHERE classID = ?",
[classID],
function (err, result) {
if (err) {
res.status(500).send("Something went wrong");
}
if (result.length !== 0) {
res.status(409).send("A pacesetter for this class already exists.");
} else {
let parentArr = [
{
classID: classID,
teacherID: teacherID,
subjectID: subjectID,
pacesetterList: pacesetterList,
createdAt: createdAt,
},
];
let newArr = [];
parentArr.forEach((parent) => {
parent.pacesetterList.forEach((child) => {
newArr.push({
classID: parent.classID,
teacherID: parent.teacherID,
subjectID: parent.subjectID,
startDate: child.startDate,
endDate: child.endDate,
objectives: child.objectives,
createdAt: parent.createdAt,
});
});
});
newArr.forEach((data) => {
db.query(
"INSERT INTO pacesetterIndex SET classID = ?, teacherID = ?, subjectID = ?, startDate = ?, endDate = ?, objectives = ?, createdAt = ?;",
[
data.classID,
data.teacherID,
data.subjectID,
data.startDate,
data.endDate,
data.objectives,
data.createdAt,
]
);
});
resolve();
}
}
);
});
Here is the code that selects the data:
const insert = async () => {
try {
const q1 = () => {
return new Promise((res, rej) => {
db.query(
"SELECT studentID, classID FROM classStudent WHERE classID = ?;",
[classID],
(err, row) => {
if (err) {
return rej(err);
} else {
res(row);
}
}
);
});
};
const q2 = () => {
return new Promise((res, rej) => {
db.query(
"SELECT pacesetterID FROM pacesetterIndex WHERE classID = ?;",
[classID],
(err, row) => {
if (err) {
return rej(err);
} else {
res(row);
}
}
);
});
};
const arr1 = await q1();
const arr2 = await q2();
let arr3 = [];
for (let i = 0; i < arr1.length; i++) {
for (let j = 0; j < arr2.length; j++) {
arr3.push({ ...arr2[j], ...arr1[i] });
}
}
console.log("Array 1", arr1.length);
console.log("Array 2", arr2.length);
console.log("Array 3", arr3.length);
arr3.forEach((data) => {
db.query(
"INSERT INTO pacesetterEntries SET pacesetterID = ?, classID = ?, studentID = ?;",
[data.pacesetterID, data.classID, data.studentID]
);
});
} catch (err) {
console.log(err);
}
};
And then both functions are called like this:
async function main() {
await pi();
await insert();
}
main();
This function contains 3 MySQL queries, 2 SELECT queries and 1 INSERT query. The first SELECT query (SELECT studentID, classID...) works every single time. But the second SELECT query (SELECT pacesetterID FROM....) only works the first time after the API starts. Or, pretty much whenever it feels like it.
The problem here is that the third and final query (INSERT INTO pacesetterEntries SET...) does not run if the second query returns now rows.
I have never come across anything like this before, if anyone has any ideas whatsoever I would be incredibly grateful.
As you can see I console.log as much as I can to see if the correct data is being passed through as the function runs. Query 2's console.log(res.length) contains a value maybe 10% of all the times this function is called.
I’m wondering if it is mysql2 that may be causing the issues with returning results for q2, it doesn’t seem to enjoy working with promises. But then again, my code may be poor. I would like to avoid using timeout at all costs, I’d like the function to run as it should - call one query and then move on to the next.
Please let me know if I can supply any more code. Note, I am using mysql2 and a connection pool to perform the db calls
I solved it with a setTimeout in the first function - pi().
const pi = async () => {
return new Promise((resolve) => {
db.query(
"SELECT classID FROM pacesetterIndex WHERE classID = ?",
[classID],
function (err, result) {
if (err) {
res.status(500).send("Something went wrong");
}
if (result.length !== 0) {
res.status(409).send("A pacesetter for this class already exists.");
} else {
let parentArr = [
{
classID: classID,
teacherID: teacherID,
subjectID: subjectID,
pacesetterList: pacesetterList,
createdAt: createdAt,
},
];
let newArr = [];
parentArr.forEach((parent) => {
parent.pacesetterList.forEach((child) => {
newArr.push({
classID: parent.classID,
teacherID: parent.teacherID,
subjectID: parent.subjectID,
startDate: child.startDate,
endDate: child.endDate,
objectives: child.objectives,
createdAt: parent.createdAt,
});
});
});
newArr.forEach((data) => {
db.query(
"INSERT INTO pacesetterIndex SET classID = ?, teacherID = ?, subjectID = ?, startDate = ?, endDate = ?, objectives = ?, createdAt = ?;",
[
data.classID,
data.teacherID,
data.subjectID,
data.startDate,
data.endDate,
data.objectives,
data.createdAt,
]
);
});
setTimeout(resolve, 500); <-- Made all my problems disappear
}
}
);
});
};
My only concern is, pi() will require different amounts if time based on how much data is being passed to the function and the server hardware . If the setTimeout isn't long enough, the function won't finish before insert() decides it's tired of waiting and then fires. Any ideas on how to prevent this?
I'm making a time card app.
but const updatesql = "UPDATE users SET ? WHERE ?"; does not work well...
How to use MySQL's PlaceHolder and Node.js ?
Especially, double placeholder SET ? WHERE ? .
const checksql = "SELECT * FROM users WHERE name = ?";
const checkname = "SELECT status FROM users WHERE name = ";
const updatesql = "UPDATE users SET ? WHERE ?";
if (req.body.begin_button) {
var name_checked = await query(checksql,{ name:
req.body.input_name });
var status_checked = await query(checkname,{ name: req.body.input_name});
if (name_checked == 0) {
var results = await query(sql, { id: id, name:
req.body.input_name, email: req.body.input_mail, start: now, status: 1 });
} else {
console.log("error");
};
} else if (req.body.finish_button){
if (name_checked != 0){
var results = await query(updatesql, { end: now, status: 0});
} else {
console.log("error");
}
} else if (req.body.start_button) {
if (status_checked == 1) {
var results = await query(updatesql, {restbegin: now,status: 2 });
} else {
console.log("error");
};
} else if (req.body.end_button) {
if (status_checked == 2) {
var results = await query(updatesql, { restend: now, status: 3 });
} else {
console.log("error");
};
};
You can do something like this
var sql = 'SELECT * FROM customers WHERE name = ? OR address = ?';
con.query(sql, [name, adr], function (err, result) {
if (err) throw err;
console.log(result);
});
So I have files inside the following folder:
app/controller/token.js
app/controller/news.js
token.js:
"use strict";
var connection = require("../con");
exports.isTokenExists = function(token) {
var checkToken = "SELECT COUNT(`id`) AS 'total' FROM `user` WHERE `token` = '" + token + "'";
var isExists = false;
var count;
var checkResult;
connection.query(checkToken, function(error, rows) {
if (!error) {
checkResult = JSON.parse(JSON.stringify(rows));
for (var i = 0; i < checkResult.length; i++) {
var row = rows[i];
count = row.total;
}
if (count > 0) {
isExists = true;
}
}
});
return isExists;
};
news.js:
"use strict";
var response = require("../response/responses");
var connection = require("../con");
var getToken = require("./token");
exports.news = function(req, res) {
response.send(false, "News API", null, res);
};
exports.allNews = function(req, res) {
var checkTokenExists = getToken.isTokenExists("75d12cc4dc07608d5b87a6cba33cac056df1239c");
if (checkTokenExists) {
var allNewsQuery = "SELECT a.`id`, b.`title` AS `category`, a.`title`, a.`description`, a.`content`, a.`image`, a.`created_date` FROM `news` AS a LEFT JOIN `news_category` AS b ON a.`id_news_category` = b.`id` ORDER BY `created_date` DESC LIMIT 20";
connection.query(allNewsQuery, function(error, rows) {
if (error) {
response.send(true, "" + error, null, res);
} else {
var data = [];
var newsData = JSON.parse(JSON.stringify(rows));
for (var i = 0; i < newsData.length; i++) {
var row = rows[i];
data[i] = {
id: row.id,
idCategory: row.idCategory,
category: row.category,
title: row.title,
description: row.description,
image: row.image,
createdDate: row.created_date
};
}
response.send(false, "News is not empty", data, res);
}
});
} else {
response.send(true, "Error: Token not found", checkTokenExists, res);
}
};
I always getting false value from isTokenExists meanwhile the token is exists in the table.
How do I get true response if the token is exist and how do I get false response if the token is not exists in table?
Any help will be much appreciated.
Regards.
The issue here is that connection.query accepts a callback, but the rest of your code will move passed that without awaiting the result, which is why your isExists always returns false. You can fix this by encapsulating the query with a Promise like this:
"use strict";
const connection = require("../con");
exports.isTokenExists = async function(token) {
const checkToken = "SELECT COUNT(`id`) AS 'total' FROM `user` WHERE `token` = ?";
return new Promise((resolve, reject) => {
connection.query(checkToken, token, function (error, results) {
if (error) return reject(error);
return resolve(results.length > 0);
});
});
};
I also simplified the logic in the callback a bit.
Then, in news.js await the result like this:
exports.allNews = async function(req, res) {
getToken.isTokenExists("75d12cc4dc07608d5b87a6cba33cac056df1239c")
.then(result => {
if (result === true) {
//place your code for handling if the token exists here
}
else {
//place your code for handling if the token does not exist
}
})
.catch(err => {
//handle error
});
}
You are missing async / await concept. You need to wait until your query executes.
1) Write a promise function
export.getCount = function(query) {
return new Promise((res, rej) => {
let count = 0;
connection.query(checkToken, function(error, rows) {
if (!error) {
checkResult = JSON.parse(JSON.stringify(rows));
for (var i = 0; i < checkResult.length; i++) {
var row = rows[i];
count = row.total;
}
}
return res(count);
})
}
2) Write async function which supports await operations
exports.isTokenExists = async function(token) {
var query = "SELECT COUNT(`id`) AS 'total' FROM `user` WHERE `token` = '" + token + "'";
let count = await getCount(query)
return count > 0; // Returns true if count is > 0
};
I'm trying to understand why the debugger does not go into the callback function, it does not give any errors or any results... It just jump over connect.query!
When I run in the mySQL workbench the code runs and I get the data, so the query is not incorrect either.. (You can see the example from the creator of the mysql node package, I can't understand why I can't get into the callback)
SELECT * FROM eclasstree WHERE numberofdigits = '8';
Here is the part of the code that does not enter the callback, all the other SQL queries works above works just fine...
connection.query("SELECT * FROM eclasstree WHERE numberofdigits = '8'", function(error, results, fields) {
if (error) {
throw error;
}
console.log(results, fields);
});
index.js // route /generatewordsconnectedtoeclass
require("console-stamp")(console, "[HH:MM:ss.l]");
const express = require("express");
const router = express.Router();
const { Database, mySQLConnectionDetails, connection } = require("../helpers/mySQL");
const { cleanseString, cleanseStringToArray, generateCountDuplication, sortValuesBykey, generateScoreArray, calculateAverage, replaceAbbreviationWithExpansion } = require("../helpers/stringFixers");
const database = new Database(mySQLConnectionDetails);
router.get("/generatewordsconnectedtoeclass", (req, res) => {
const eClassArray = [];
let eClassCode = "";
connection.query("SELECT * FROM eclasstree WHERE numberofdigits = '8'", function(error, results, fields) {
results.forEach(eclassobj => {
eClassCode = eclassobj.code;
connection.query(`SELECT itemnumber, cleanname, eclass FROM partnumbersclassified WHERE eclass = '${eclassobj.code}'`, function(error, results, fields) {
let stringToArray = [];
let countObject = [];
if(results.length > 0) {
stringToArray = cleanseStringToArray(results, "cleanname");
}
if(stringToArray.length > 0) {
countObject = generateCountDuplication(stringToArray);
// console.log(countObject);
for (const property in countObject) {
if (countObject.hasOwnProperty(property)) {
// console.log(property + " : " + countObject[property] + " : " + eClassCode);
// console.log(property);
// const obj = {
// eclasscode: `${eClassCode}`,
// wordcount: `${countObject[property]}`
// };
// obj[property] = `${countObject[property]}`;
// const obj2 = obj;
// connection.query(`INSERT INTO wordsconnectedtoeclasscode (eclasscode, word, wordcount) VALUES (${eClassCode}, ${property}, ${countObject[property]})`, function(error, results, fields) {
// const post = {word: "Hello", wordcount: "1"};
// connection.connect();
connection.query("SELECT * FROM eclasstree WHERE numberofdigits = '8'", function(error, results, fields) {
if (error) {
throw error;
}
console.log(results, fields);
});
// connection.query("INSERT INTO posts SET ?", post, function(error, results, fields) {
// //connection.query("INSERT INTO wordsconnectedtoeclasscode (eclasscode, word, wordcount) VALUES ('12345123', 'balle', '2'})", function(error, results, fields) {
// if (error) throw error;
// console.log(fields);
// console.log(results);
// connection.end();
// });
}
}
}
});
});
});
res.json({});
});
module.exports = router;
If I do "step in-to" I can see the "sql" is defined with the query, but the "cb" is undefined!
With help of #Patrick Evans I solved it.
I read up on the docs for the mysql node package and they do not follow the standard mysql queries. So after I changed it, it worked!
const obj = {
eclasscode: `${eclassobj.code}`,
wordcount: `${countObject[property]}`,
word: property
};
connection.query("INSERT INTO wordsconnectedtoeclasscode SET ?", obj, function(error, results3) {
if (error) {
throw error;
}
console.log(results3.insertId);
});
require("console-stamp")(console, "[HH:MM:ss.l]");
const express = require("express");
const router = express.Router();
const { Database, mySQLConnectionDetails, connection } = require("../helpers/mySQL");
const { cleanseString, cleanseStringToArray, generateCountDuplication, sortValuesBykey, generateScoreArray, calculateAverage, replaceAbbreviationWithExpansion } = require("../helpers/stringFixers");
const database = new Database(mySQLConnectionDetails);
router.get("/generatewordsconnectedtoeclass", (req, res) => {
connection.query("SELECT * FROM eclasstree WHERE numberofdigits = '8'", function(error, results1) {
results1.forEach(eclassobj => {
connection.query(`SELECT itemnumber, cleanname, eclass FROM partnumbersclassified WHERE eclass = '${eclassobj.code}'`, function(error, results2) {
let stringToArray = [];
let countObject = [];
if(results2.length > 0) {
stringToArray = cleanseStringToArray(results2, "cleanname");
}
if(stringToArray.length > 0) {
countObject = generateCountDuplication(stringToArray);
for (const property in countObject) {
if (countObject.hasOwnProperty(property)) {
const obj = {
eclasscode: `${eclassobj.code}`,
wordcount: `${countObject[property]}`,
word: property
};
connection.query("INSERT INTO wordsconnectedtoeclasscode SET ?", obj, function(error, results3) {
if (error) {
throw error;
}
console.log(results3.insertId);
});
}
}
}
});
});
// res.json({});
});
});
module.exports = router;
At the moment I have a list of Team ID's which I have stored in the array teamIds. I also have a function findByKey in my Team mongoose schema which finds a Team based on its key. As you can see from the code I have to put each new Team.findByKey inside the previous one, if I put it outside of the previous findByKey it doesn't function correctly.
I'm having problems putting the Team.findByKey methods into some sort of for loop which can loop through the array teamIds and for each Team in the array. I am developing the function to create a new tournament, the idea is that you pass an array of teamIds to here, and it loops through each ID, searching for that Team and adding it to a teamsList array in order to create the tournament.
I need to put the last bit of code to create the array of Team objects into the last Team.findByKey method which is my problem. How would I fix this so that I can pass it n amount of teams and find each team and store it as an array of Teams?
This is my code:
app.get('/tournament', function(req, res){
function genMatches(nTeams) {
var matchArray = [];
while (nTeams > 1) {
nTeams = nTeams >> 1;
var matches = [];
for (var i = 0; i < nTeams; ++i) {
matches.push([]);
}
matchArray.push(matches);
}
return matchArray;
}
var teamIds = [
1364472344972,
1363173222886,
1363007586845,
1363007557484
]
var tournamentName = 'My Tournament';
Team.findByKey(teamIds[0], function(err, team1) {
if(err) {
util.log("Error occured");
}
if(!team1) {
util.log("The team does not exist");
}
Team.findByKey(teamIds[1], function(err, team2) {
if(err) {
return util.log("Error occured");
}
if(!team2) {
return util.log("The team does not exist");
}
Team.findByKey(teamIds[2], function(err, team3) {
if(err) {
return util.log("Error occured");
}
if(!team3) {
return util.log("The team does not exist");
}
Team.findByKey(teamIds[3], function(err, team4) {
if(err) {
return util.log("Error occured");
}
if(!team4) {
return util.log("The team does not exist");
}
var teamList = [
team1._id,
team2._id,
team3._id,
team4._id
];
var numRounds = Math.log(teamList.length)/Math.log(2);
var matches = genMatches(teamList.length);
for(var i = 0; i < matches[0].length; i++){
matches[0][i] = [ teamList[i+i], teamList[i+(i+1)] ]
}
var tournament = new Tournament({
name: tournamentName,
teams: teamList,
rounds: numRounds,
matches: matches
});
res.send(tournament);
});
});
});
});
});
Team schema:
'use strict';
var util = require('util');
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var validatePresenceOf = function(value){
return value && value.length;
};
var toLower = function(string){
return string.toLowerCase();
};
var getId = function(){
return new Date().getTime();
};
/**
* The Team schema. we will use timestamp as the unique key for each team
*/
var Team = new Schema({
'key' : {
unique : true,
type : Number,
default: getId
},
'name' : { type : String,
validate : [validatePresenceOf, 'Team name is required'],
index : { unique : true }
}
});
/**
* Get complete team details for all the teams
*/
Team.statics.getAll = function(cb){
var query = this.find({});
query.sort({key : -1});
return query.exec(cb);
};
Team.statics.findByKey = function(key, cb){
return this.find({'key' : key}, cb);
};
Team.statics.findByName = function(name, cb) {
return this.find({'name' : name}, cb);
};
module.exports = mongoose.model('Team', Team);
You can use the $in operator to look up your four teams in one query:
Team.find({key: {$in: teamIds}}, function (err, teams) {
...
});
If for some reason you need to call findByKey multiple times instead of collapsing it all into a single $in, look at using the async library's each method to do that more cleanly.