I got a data from MySQL and push it into new Array but it when I log it. It doesn't have any data. I use for loop to get each data from DB and I don't know how to push RowDataPacket into new Array.
Or is there any way to combine two SQL into one SQL line?
router.get(`/find-users/:queryString`, function(req, res, next) {
let queryString = req.params.queryString;
db.query(
`SELECT distinct userId from project WHERE keyword like "%${queryString}%"`,
function(error, data) {
if (error) {
console.log(error);
}
// console.log(data);
let userArray = [];
for (let i = 0; i < data.length; i++) {
db.query(
`SELECT * FROM user WHERE loginId='${data[i].userId}'`,
function(error, userData) {
if (error) {
console.log(error);
} else {
console.log("-----------------------");
console.log(userData[0]);
// userArray[i] = userData;
userArray.push(userData[0]);
}
}
);
}
console.log(`-------`);
console.log(userArray);
console.log(`-------`);
}
);
});
I have to make array like this.
[ RowDataPacket {
loginId: '박동찬',
displayId: '107688875506148574770',
name: '박동찬',
bio: 'NO BIO',
RowDataPacket {
loginId: 'jaagupkymmel',
displayId: '1156051',
name: 'Jaagup Kümmel',
bio: 'NO BIO' }
]
But it only returns like this
Result
-------
[]
-------
const {promisify} = require('util')
router.get(`/find-users/:queryString`, async function (req, res, next) {
const query = promisify(db.query).bind(db);
let queryString = req.params.queryString;
const data = await query(`SELECT distinct userId from project WHERE keyword like "%${queryString}%"`)
if (!data) {
console.log("error");
}
// console.log(data);
let userArray = [];
for (let i = 0; i < data.length; i++) {
const userData = await query(`SELECT * FROM user WHERE loginId='${data[i].userId}'`)
if (!userData) {
console.log("error");
} else {
console.log("-----------------------");
console.log(userData[0]);
// userArray[i] = userData;
userArray.push(userData[0]);
}
}
console.log(`-------`);
console.log(userArray);
console.log(`-------`);
});
use this instead
function(error, userData, fields)
and you get an array like shown here https://www.w3schools.com/nodejs/nodejs_mysql_select.asp
And please read up on sql injection and node.js Preventing SQL injection in Node.js
in addition to above answer,
[{
RowDataPacket: {
loginId: '박동찬',
displayId: '107688875506148574770',
name: '박동찬',
bio: 'NO BIO',
RowDataPacket: {
loginId: 'jaagupkymmel',
displayId: '1156051',
name: 'Jaagup Kümmel',
bio: 'NO BIO' }
}
}]
the json should be key value pair other it wont work.
Related
I have been trying like crazy to find a solution to my problem, but nothing seems to work and I don't know where I am going wrong. I am creating an app using the PERN stack, and I have an array of data with a length of 24.
I iterate through my data array with following snippet of code (this is after trying to find solutions but the result is always the same):
const createEntry = async function (data) {
let whatever = await Promise.all(
data.map(async (item) => {
try {
console.log(`${item.name}`);
await Entry.post("/", item); //call to database
} catch (err) {
console.log(err);
}
})
);
whatever.then(console.log("I hate my life."));
};
I know the entire data array is being iterated through because of the console.logs, but the call to Entry.post() is only happening like maybe six times, and I am not getting all of my data entered into my database.
My express app.post code looks like this:
app.post("/url", async (req, res) => {
try {
const results = await db.query(
"INSERT INTO database (id, name) values ($1, $2)",
[
req.body.id,
req.body.name,
]
);
res.send({
status: "success",
results: results.rows.length,
data: {
entry: results.rows[0],
},
});
} catch (err) {
console.log(`${err.detail} for ${req.body.name}`);
}
});
So, I resolved this on my own and found a working solution.
My createEntry code from my question:
const createEntry = async function (data) {
let whatever = await Promise.all(
data.map(async (item) => {
try {
console.log(`${item.name}`);
await Entry.post("/", item); //call to database
} catch (err) {
console.log(err);
}
})
);
whatever.then(console.log("I hate my life."));
};
now looks like this:
const createEntry = async function (data) {
try {
let result = await CreateDB.post("/", data);
return result;
} catch (err) {
console.log(err);
}
};
And my app.post code
app.post("/url", async (req, res) => {
try {
const results = await db.query(
"INSERT INTO database (id, name) values ($1, $2)",
[
req.body.id,
req.body.name,
]
);
res.send({
status: "success",
results: results.rows.length,
data: {
entry: results.rows[0],
},
});
} catch (err) {
console.log(`${err.detail} for ${req.body.name}`);
}
});
Now looks like this:
app.post("/url", async (req, res) => {
try {
const results = await db.query(
"INSERT INTO database (id, name) values ($1, $2)",
[
req.body.id,
req.body.name,
]
);
res.send(res.rows[0]);
} catch (err) {
console.log(`${err.detail} for ${req.body.name}`);
}
});
And my call to my createEntry is:
let temp = {obj: some object};
createEntry(temp).then((newEntry) => {
dbArray.push(newEntry.data);
manipulateData(newEntry.data);
});
And with this I am now able to create a database entry, retrieve the database object and do work with it and it works for any size array which makes me really happy. So hopefully, if anyone has a similar problem, this can help.
i'm trying to show a user specific data using req.session.user and pass the ID to the criteria i'm building. (every entry also has a user field so i can match) yet it does not work.
The Service :
async function query(filterBy) {
try {
const criteria = _buildCriteria(filterBy);
const collection = await dbService.getCollection('tab');
const tabs = await collection.find(criteria).toArray();
// const userTabs = await collection.find({ user: '62be030cb4de461a8462b863' }).toArray();
return tabs;
} catch (err) {
logger.error('Can not find tabs', err);
throw err;
}
}
The console.log('userId', userId) returns the Id I get from my controller
function _buildCriteria(filterBy) {
const criteria = {};
const { text, genre, userId } = filterBy;
console.log('userId', userId);
if (text) {
const txtCriteria = { $regex: text, $options: 'i' };
criteria.name = txtCriteria;
}
if (genre) {
criteria.genre = { $eq: genre };
}
if (userId) {
criteria.user = { $eq: userId };
}
return criteria;
}
The controller :
async function getTabs(req, res) {
try {
const userId = req?.session?.user?._id;
const filterBy = req.query;
const fitlerUpdated = { ...filterBy, id: userId };
const tabs = await tabService.query(fitlerUpdated);
res.json(tabs);
} catch (err) {
logger.error('Failed to get tabs', err);
res.status(500).send({ err: 'Failer ti get tabs' });
}
}
I tried using
const userTabs = await collection.find({ user: '62be030cb4de461a8462b863' }).toArray()
and it works yet it doens't work along with the criteria.
thanks for any help!
I have realize I accidentally passed the wrong key.
should have been id and not userId
app.get("/api/users/:_id/logs", (req, res) => {
const id = req.params._id;
const { from, to, limit } = req.query;
** Here I tried to search for the matched user and it works successfully: **
User.findById({ _id: id }, (err, user) => {
if (!user || err) {
res.send("Unknown User Id !!");
} else {
**Then I tried to filter the log array with date **
// const username = user.username;
let responObject = {};
if (from) {
responObject["$gte"] = new Date(from).toDateString();
}
if (to) {
responObject["$lte"] = new Date(to).toDateString();
}
let filter = {
_id: id,
};
if (from || to) {
filter.date = responObject;
}
let nonNullLimit = limit ?? 500;
**try to build the array log and return it to the user but it always be empty and never return the exercises for the user **
Exercise.find(filter)
.limit(+nonNullLimit)
.exec((err, data) => {
if (err || !data) {
res.json([]);
} else {
const count = data.length;
const rowLog = data;
const { username, _id } = user;
const log = rowLog.map((item) => ({
description: item.description,
duration: item.duration,
date: new Date(item.date).toDateString(),
}));
console.log(log)
if (from && to) {
res.json({
username,
from: new Date(from).toDateString(),
to: new Date(to).toDateString(),
count,
_id,
log,
});
} else {
res.json({
username,
count,
_id,
log,
});
}
}
});
}
});
});
this is the result when I try to log all the exercises for the user
{"username":"ahmed","count":0,"_id":"62a9aab2743ddfc9df5165f2","log":[]}
I am new to firebase and would like to implement the ranking for the players stored in the rank table from firebase real-time db, see screenshot below:
I have also setup the rules for the index:
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"TH": {
"rank": {
".indexOn" : ["balance", "w_rate","match"]
}
}
}
}
in my firebase function, I have a function as a post request to get the rank:
exports.getRank = functions.https.onRequest(async (req,res) => {
const user_id = req.query.id;
console.log(`user_id ${user_id} `);
const query = database().ref('TH/rank')
.orderByChild('balance')
.limitToLast(30)
query.once('value',function(snapshot) {
console.log('in side the usersRef');
console.log(`snapshot:${JSON.stringify(snapshot.val())}`);
let current_user_rank = 0;
if (user_id !== null) {
console.log(`user id ${user_id} isn't null`);
database().ref('TH/rank/').orderByChild('balance').once('value',function(all_snapshot){
let index = 0;
console.log(`user id ${user_id} all snapshot.`);
if (all_snapshot.child(`${user_id}`).exists()) {
console.log(`user id ${user_id} exists`);
const current_user_data = all_snapshot.child(`${user_id}`).val();
all_snapshot.forEach( child => {
index += 1;
console.log(child.key, child.val());
if(child.key === user_id) {
current_user_rank = all_snapshot.numChildren() - index;
}
});
res.json({
user: { id: user_id,
rank: current_user_rank,
data: current_user_data
},
rank: snapshot.val()
});
} else {
res.json({
user: { id: user_id,
rank: current_user_rank,
data: null
},
rank: snapshot.val()
});
}
}).catch();
} else {
res.json({
user: { id: user_id,
rank: current_user_rank,
data: null
},
rank: snapshot.val()
});
}
}).catch();
});
However, the result isn't correct, it seems the orderByChild doesn't work at all. Can someone help on this?
Thanks.
There are several problems with your Cloud Function:
You use async when declaring the callback but you never use await in the Cloud Function, in order to get the result of the asynchronous once() method.
Instead of using the callback "flavor" of the once() method (i.e. ref.once('value',function(snapshot) {..}), use the promise "flavor" (i.e., with await: await ref.once('value');).
The result is that you don't correctly manage the Cloud Function life cycle. For more details on how to do that correctly, I would suggest you watch the 3 videos about "JavaScript Promises" from the Firebase video series as well as read the following doc.
So the following should do the trick. (Note that I've just adapted it to correctly manage the life cycle, I've not tested the business logic).
exports.getRank = functions.https.onRequest(async (req, res) => {
try {
const user_id = req.query.id;
console.log(`user_id ${user_id} `);
let current_user_rank = 0;
if (user_id !== null) {
console.log(`user id ${user_id} isn't null`);
const baseQuery = database().ref('TH/rank/').orderByChild('balance');
const query = baseQuery.limitToLast(30);
const snapshot = await query.once('value');
console.log(`snapshot:${JSON.stringify(snapshot.val())}`);
const all_snapshot = await baseQuery.once('value');
let index = 0;
console.log(`user id ${user_id} all snapshot.`);
if (all_snapshot.child(`${user_id}`).exists()) {
console.log(`user id ${user_id} exists`);
const current_user_data = all_snapshot.child(`${user_id}`).val();
all_snapshot.forEach(child => {
index += 1;
console.log(child.key, child.val());
if (child.key === user_id) {
current_user_rank = all_snapshot.numChildren() - index;
}
});
res.json({
user: {
id: user_id,
rank: current_user_rank,
data: current_user_data
},
rank: snapshot.val()
});
} else {
res.json({
user: {
id: user_id,
rank: current_user_rank,
data: null
},
rank: snapshot.val()
});
}
} else {
res.json({
user: {
id: user_id,
rank: current_user_rank,
data: null
},
rank: snapshot.val()
});
}
} catch (error) {
console.log(error);
res.status(500).send(error);
}
});
Update following your comment:
You need to use forEach() in order to get the children correctly ordered, and not snapshot.val(). snapshot.val() displays the children according to their key, exactly like they are ordered in the DB. The following adaptation of the code in your comment works correctly:
exports.getSortedRank = functions.https.onRequest(async (req, res) => {
try {
const obj = {};
const baseQuery = admin.database().ref('TH/rank/').orderByChild('balance');
const query = baseQuery.limitToLast(10);
const snapshot = await query.once('value');
snapshot.forEach(childSnapshot => {
console.log(childSnapshot.val());
obj[childSnapshot.key] = childSnapshot.val()
});
res.json({ rank: obj });
} catch (error) { console.log(error); res.status(500).send(error); }
});
I'm trying to create an api route using Node and Express and I must say I don't have much experience with it. Right know I have the following code:
app.get('/api/place/:id', (req, res) => {
var id = req.params.id;
var message_error = '{"status": "failed", "message": "Unable to fetch data"}';
db.query("SELECT `id`, `user`, `lat`, `lon`, `elevation`, `rating`, `rating_count`, `country`, `continent`, `locality` FROM `t_points` WHERE id = ?", [id], (err, res1) => {
if(err) {
res.json(message_error);
} else {
//Store the user id from the points table and use it to fetch user datas
var userId = res1[0].user;
if(userId != null) {
db.query("SELECT `id`, `name` FROM `t_users` WHERE `id` = ?", [userId], (err, res2) => {
if(err) {
res.json(message_error);
} else {
//Final json structure
res.json({
id: res1[0].id,
lat: res1[0].lat,
lon: res1[0].lon,
elevation: res1[0].elevation,
rating: res1[0].rating,
rating_count: res1[0].rating_count,
user: {
id: res2[0].id,
name: res2[0].name
}
});
}
});
} else {
res.json({
id: res1[0].id,
lat: res1[0].lat,
lon: res1[0].lon,
elevation: res1[0].elevation,
rating: res1[0].rating,
rating_count: res1[0].rating_count
});
}
}
});
});
I'm hard-coding the json structure so if the userId in my table is null I don't print the user object in the json, otherwise I print it. But that's not a good idea, as I will also add more queries in the same route. Is there a simple way to create just one json at the end of all the queries and if some values are null not showing it?
Also, would it be better to use async and await functions to do it, instead of this way?
Thanks!
use util maybe better way to get result when querying data.
const mysql = require('mysql');
const util = require('util');
// ? connection pool
let db = mysql.createPool({
connectionLimit: 10,
host: 'localhost',
port: 3306,
user: 'root',
password: 'secretpass',
database: 'yourdatabasename'
});
// ? check connection
db.getConnection((err, connection) => {
if (err) {
console.log('database connection failed');
} else {
console.log('database connection resolved');
connection.release();
}
});
// ? formatter query
function queryString(spName, ...queryParam) {
return mysql.format(spName, queryParam);
}
// ? do query
let performQuery = util.promisify(db.query).bind(db)
module.exports = {
performQuery,
queryString
}
then use the function above like this :
app.get('/api/place/:id', async (req, res) => {
const id = req.params.id;
const message_error = '{"status": "failed", "message": "Unable to fetch data"}';
try {
let prepareOne = queryString(SELECT `id`, `user`, `lat`, `lon`, `elevation`, `rating`, `rating_count`, `country`, `continent`, `locality` FROM `t_points` WHERE id = ?", id);
let resultOne = await performQuery(prepareOne);
let userId = resultOne[0].user;
if (userId != null) {
let prepareTwo = queryString("SELECT `id`, `name` FROM `t_users` WHERE `id` = ?", userId);
let resultTwo = await performQuery(prepareTwo);
res.json({
...resultOne,
user: {
...resultTwo
}
});
}
} catch (err) {
res.send(message_error);
}