How to render multiple mysql queries using node in one http request - javascript

I need to make two query's from different tables, how should i do it, to output data in new page. Now it is working with one query.
exports.getAllImages = function () {
return new Promise((resolve, reject) => {
con.query("SELECT * FROM products WHERE product_group='TRENCH
CONVECTORS'", function (err, result, fields) {
if (err) reject(err);
resolve(result);
});
});
}
//This is what i tried, but it does not work
router.get('/product/:id', async function(req, res, next) {
let filesFromFolder;
let allimages
database.retreaveImage(req.params.id).then(function(value) {
filesFromFolder = value;
});
database.getAllImages().then(function(value){
allimages = value;
})
res.render('product.ejs', {
productName: req.params.id,
data: filesFromFolder,
allimages: allimages
});
});
//This code works, and i am using it now
router.get('/product/:id', async function(req, res, next) {
let filesFromFolder;
database.retreaveImage(req.params.id).then(function(value) {
filesFromFolder = value;
res.render('product.ejs', {
productName: req.params.id,
data: filesFromFolder
});
});
});
How should i edit the code to execute two query's?

You need to render your page when you received response from both queries.
You can use Promise.all() method for this.
Promise.all([
database.retreaveImage(req.params.id),
database.getAllImages()
]).then(resultArr => {
filesFromFolder = resultArr[0];
allimages = resultArr[1];
res.render("product.ejs", {
productName: req.params.id,
data: filesFromFolder,
allimages: allimages
});
});

I'm not sure if you want a single query who retrieve data from two tables or if you want 2 different queries from 2 table...if the second, you can concatenate functions to have a linear flow of data
//This code works, and i am using it now
router.get('/product/:id/:temp', async function(req, res, next) {
let filesFromFolder;
database.retreaveImage(req.params.id).then(function(value) {
var filesFromFolder = value;
//Using a temp function
database.retreaveTemp(req.params.temp).then(function(value_temp) {
var filesFromTemp = value_temp;
res.render('product.ejs', {
productName: req.params.id,
data: filesFromFolder,
dataTemp: filesFromTemp
});
});
});
});

Related

PERN stack: Iterating through array of data, my call to my database is not going through for every data record

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.

Sending results from multiple mongo DB queries in one route to my view

I'm trying to get 2 sets of data from my database using simple mongo db queries. since im using 2 queries, how do I then pass both results to the view? I'm getting an internal server error currently. I want to be able to show the entire list of guardians and then show how many they are in a span.
Thank you very much
here is my code:
//show guardians
router.get('/guardians', middleware.isAdmin, function (req, res) {
//ShOW ADMIN ALL guardians
User.find({ isAdmin: false }, function (err, guardian) {
if (err) {
console.log(err);
} else {
res.render('guardians', { guardian: guardian, currentUser: req.user });
}
});
//Count all guardians
User.countDocuments({isAdmin: false}, function (err, result) {
if (err) {
res.send(err);
} else {
var allGuardians = result;
res.render('guardians', { allGuardians: allGuardians });
}
});
});
You can do this:
router.get('/guardians', middleware.isAdmin, function (req, res) {
//ShOW ADMIN ALL guardians
let prom1 = User.find({ isAdmin: false })
//Count all guardians
let prom2 = User.countDocuments({isAdmin: false});
Promise.all([prom1, prom2]).then(result => {
// do your things
//results will be array and you can get
//response of prom1 in result[0]
//response of prom1 in result[1]
//pass the data to view
}).catch(err => {
//handle your error here
console.log(`Error : ${err}`);
})
});

How adding a field from a pulled mongodb document

I am trying to use an api to get the current value of a stock and multiply by the users stock.
When I make a call the route I get empty data, and when I print the value of the callback I get an empty array
function user_cur_portfolio(port, callback) {
let portfolio = [];
port.forEach( (stock) => {
var ticker = stock.name.toLowerCase();
alpha.data.quote(`${ticker}`).then(data => {
var fixed = Number((data['Global Quote']['05. price'] * stock.shares).toFixed(2));
let curr = {
name : ticker,
shares: stock.shares,
value : fixed
}
portfolio.push(curr)
});
})
callback(portfolio)
}
router.get('/portfolio', (req, res, next) => {
if (req.session.userId !== undefined){
User.findOne({ _id : req.session.userId }).exec(function (err, user) {
if (err)
next(err);
user_cur_portfolio(user.portfolio, (port)=>{
console.log(port);
res.render('portfolio', { portfolio: port, balance: user.balance});
});
})
} else {
res.redirect('/users/login');
}
});
When I make a call the route I get empty data Because alpha.data.quote is an async function and forEach is a sync function therefore, you will not be getting data in port variable.
So the best work around to this, is to use async await with all the synchronous function to behave them like async
async function user_cur_portfolio(port) {
let portfolio = [];
await Promise.all(
port.map(async stock => {
var ticker = stock.name.toLowerCase();
const data = await alpha.data.quote(`${ticker}`);
var fixed = Number((data['Global Quote']['05. price'] * stock.shares).toFixed(2));
let curr = {
name: ticker,
shares: stock.shares,
value: fixed
};
portfolio.push(curr);
})
);
return portfolio;
}
router.get('/portfolio', (req, res, next) => {
if (req.session.userId !== undefined) {
User.findOne({ _id: req.session.userId }).exec(async function(err, user) {
if (err) next(err);
const port = await user_cur_portfolio(user.portfolio);
console.log(port);
res.render('portfolio', { portfolio: port, balance: user.balance });
});
} else {
res.redirect('/users/login');
}
});

How to give some condition to elastics search query

I have a NodeJS application which is using mongoosastic api for Elasticsearch. Now I need a way of adding a condition(isDeleted == false) to the specified query(query: req.query.q).
this is my code
exports.search = function (req, res) {
if (!req.query.q) return res.status(400).send('No Query Provided')
log.error(req.query.q)
User.search({query_string: {query: req.query.q}}, (err, results) => {
if (err) return handleError(res, err)
var ret = _.map(results.hits.hits, result => ({
userID: result._id,
_score: result._score,
name: result._source.name,
loc: result._source.loc,
info: result._source.info,
images: result._source.images
}))
return res.send(ret)
})
}
How can I do that?
You can use filtering to filter your data. Check the example of your plugin website. Following example is your answer also.
var geoQuery = {query_string: {query: req.query.q}};
var myFilter = {
term: {
isDeleted: true
}
};
User.search(geoQuery, {filter: myFilter}, function(err, res) { /* ... */ })

Multiple node.js requests

My controller is using the request package to make server-side HTTP requests to another API. My question is how can I make MULTIPLE of these requests? Here is my current code:
** UPDATED CODE **
module.exports = function (req, res) {
var context = {};
request('http://localhost:3000/api/single_project/' + req.params.id, function (err, resp1, body) {
context.first = JSON.parse(body);
request('http://localhost:3001/api/reports/' + req.params.id, function (err, resp2, body2) {
context.second = JSON.parse(body2); //this line throws 'SyntaxError: Unexpected token u' error
res.render('../views/project', context);
});
});
};
I need to make two more of those calls and send the data returned from it to my template...
Can someone help?
Thanks in advance!
function makePromise (url) {
return Promise(function(resolve, reject) {
request(url, function(err, resp, body) {
if (err) reject(err);
resolve(JSON.parse(body));
});
});
}
module.exprts = function (req, res) {
let urls = ['http://localhost:3000/api/1st',
'http://localhost:3000/api/2st',
'http://localhost:3000/api/3st'].map((url) => makePromise(url));
Promise
.all(urls)
.then(function(result) {
res.render('../views/project', {'first': result[0], 'second': result[1], 'third': result[2]});
})
.catch(function(error){
res.end(error);
});
}
You can use Promise lib in latest nodejs.
Simple solution
Nest request calls. This is how you can handle the dependency between requests. Just make sure your parameters are unique across scopes if needed.
module.exports = function (req, res) {
var context = {};
request('http://localhost:3000/api/1st', function (err, resp1, body) {
var context.first = JSON.parse(body);
request('http://localhost:3000/api/2nd', function (err, resp2, body) {
context.second = JSON.parse(body);
request('http://localhost:3000/api/3rd', function (err, resp3, body) {
context.third = JSON.parse(body);
res.render('../views/project', context);
});
});
});
};
Simplest way if you use bluebird promise library:
var Promise = require('bluebird');
var request = Promise.promisify(require('request'));
module.exports = function (req, res) {
var id = req.params.id;
var urls = [
'http://localhost:3000/api/1st/' + id,
'http://localhost:3000/api/2st/' + id,
'http://localhost:3000/api/3st/' + id
];
var allRequests = urls.map(function(url) { return request(url); });
Promise.settle(allRequests)
.map(JSON.parse)
.spread(function(json1, json2, json3) {
res.render('../views/project', { json1: json1 , json2: json2, json3: json3 });
});
});
it executes all requests even if one (or more) fails

Categories