Render template after fetching data from mongodb - arrays

app.get('/clients', (req, res) => {
var clientArray;
MongoClient.connect('mongodb://localhost:27017/Clients', (err, db) => {
if (err) {
return console.log('Unable to Connect');
}
console.log('Connected to Mongodb server');
db.collection('Clients').find().toArray().then((docs) => {
clientArray = JSON.stringify(docs, undefined, 2);
// clientArray = docs;
console.log(clientArray);
}, (err) => {
console.log("ERROR")
});
db.close();
});
res.render('clients.hbs', {
infoArray: clientArray,
name: 'Harshit'
});
});
Here the res.render function is being called before getting the required data from the mongodb database. I want to pass the data fetched as an array to the handlebars template.
{{#each infoArray}}
<h1>{{this.name}}</h1>
{{this.region}}
{{/each}}
Here I am trying to go through the array rendered and display the data.Any Help is appreciated.
Structure of array
[{
"name": "harshit",
"region": "delhi"
},
{
"name": "mendax",
"region": "ecuador"
}
]

Render has to be in callback function :
app.get('/clients', (req, res) => {
var clientArray;
MongoClient.connect('mongodb://localhost:27017/Clients', (err, db) => {
if (err) {
return console.log('Unable to Connect');
}
console.log('Connected to Mongodb server');
db.collection('Clients').find().toArray().then((docs) => {
clientArray = JSON.stringify(docs, undefined, 2);
// clientArray = docs;
console.log(clientArray);
db.close();
res.render('clients.hbs', {
infoArray: clientArray,
name: 'Harshit'
});
}, (err) => {
console.log("ERROR")
db.close();
});
});
});

You are almost there.
This is happening becuse MongoClient.connect(.. is asynchronous. So you res.render executes before that.
What you need is, just move your res.render inside that block
app.get('/clients', (req, res) => {
var clientArray;
MongoClient.connect('mongodb://localhost:27017/Clients', (err, db) => {
if (err) {
return console.log('Unable to Connect');
}
console.log('Connected to Mongodb server');
db.collection('Clients').find().toArray().then((docs) => {
clientArray = JSON.stringify(docs, undefined, 2);
// clientArray = docs;
res.render('clients.hbs', {
infoArray: clientArray,
name: 'Harshit'
});
}, (err) => {
console.log("ERROR")
});
db.close();
});
});

Related

How to Properly Send to Socket Room?

The 'message' socket is not working sending to the frontend. I think the problem is originating from my server code, specifically this block:
socket.to(data.roomId).emit('message', {
from: data.from,
body: data.body,
timestamp: data.timestamp
});
When I change the above to socket.emit('message'), the message is received and rendered on the front end. However, because it's not to the specific roomId, there is no instant chat functionality. I know data.roomId is the proper roomId using a console.log in the proper scope.
Server API
io.sockets.on('connection', function (socket) {
//meant to join the socket to the roomId so that messages can be emmitted to the roomId
socket.on('join', function (data) {
socket.join(data.roomid, () => {
console.log(data.roomid);
});
});
//my Conversation schema holds Message Schemas
socket.on('connected', function (data) {
//loads all messages already created
const filter = { roomId: data.roomid };
(async () => {
console.log('searching for Schema');
let conversation = await Conversation.findOne(filter)
.populate('messages')
.exec(function (err, message) {
if (message) {
const array = message.messages;
console.log(array);
socket.emit('send', { arra: array }); //sends previous conversation
} else {
console.log('Schema not found');
}
});
})();
});
socket.on('server:message', (data) => {
const filter = { roomId: data.roomId };
const message = new Message({
from: data.from,
body: data.body,
timestamp: data.timestamp
});
(async () => {
console.log('searching for Schema');
let conversation = await Conversation.findOneAndUpdate(filter, {
$push: { messages: message }
});
if (conversation == null) {
console.log('Schema being created');
(await Conversation.create(filter)).populate('messages');
message.save(function (err) {
if (err) console.log('an error has occured saving the message');
// saved!
});
await Conversation.findOneAndUpdate(filter, {
$push: { messages: message }
});
let updatedConversation = await Conversation.findOne(filter);
} else {
console.log('Schema found');
let updatedConversation = await Conversation.findOne(filter);
message.save(function (err) {
if (err) return handleError(err);
// saved!
});
}
})();
//this socket is not working
socket.to(data.roomId).emit('message', {
from: data.from,
body: data.body,
timestamp: data.timestamp
});
});
});
Frontend
//this socket is not receiving anything
ioClient.on('message', (msg) => {
console.log(msg); //this is not printing anything
if (isMount) {
setMessages((previousMessages) => [
...previousMessages,
toChatMessage(msg)
]);
}
});
When you broadcast to a room from a given socket using
io.on('connection', function(socket){
socket.to('some room').emit('some event');
});
Every sockets in the room excluding the sender will get the event.
In your case, you need to use io.to('some room').emit('some event');
Check out this Socket.IO Documentation

Update specific index of array in MongoDB

I would like to update the shipping property in my MongoDb (CRUD).
Shipping is an array property that contains object[index]. How to update the specific object such as index1 or index2.
This show the shipping property that contains two objects
If I want to update Object only at index 1 on the providerName, how can I do that
exports.updateShpping = (req, res) => {
const {shipping} = req.body;
Shop.findOne({ _id: req.shop._id }, (err, shop) => {
if (!shipping) {
return res.status(400).json({
error: 'shipping is required'
});
} else {
shop.shipping.push(shipping) ;
}
shop.save((err, addShipping) => {
if (err) {
console.log('Shipping ADD ERROR', err);
return res.status(400).json({
error: 'Shipping add failed'
});
}
res.json(addShipping);
});
});exports.updateShpping = (req, res) => {
const {shipping} = req.body;
Shop.findOne({ _id: req.shop._id }, (err, shop) => {
if (!shipping) {
return res.status(400).json({
error: 'shipping is required'
});
} else {
shop.shipping.push(shipping) ;
}
shop.save((err, addShipping) => {
if (err) {
console.log('Shipping ADD ERROR', err);
return res.status(400).json({
error: 'Shipping add failed'
});
}
res.json(addShipping);
});
});
};

Json; how can I return my res array of MongoDB Models to Router's .get, as json? (Node js)

I can successfully connect, query & find all of the files that I want from my database, according to my model.
But I can't actually return them as JSON yet... so my question is, how can I return this following result (console.log of res):
Into JSON for my get request?
My model with most vars snipped for brevity:
const fileSchema = new mongoose.Schema({
fileName: { type: String },
versionData: [
{
versionID: { type: Number, required: false
}
]
});
This is my main code where I am trying to return my res as JSON so that my Get request can be properly processed and display the results. I've tried returning JSON.stringify(res), but that didn't seem to work.
// Controller code
findAll = function() {
File.find({}, function(err, res) {
if (err) console.log(err);
else {
// Res is populated successfully
console.log(res);
return res.json(); // JSON.stringify(res)
}
});
};
Router:
// Return all results
router.get("/findAll", ctrlFile.findAll);
Thank you
Hey so I got this working by changing:
findAll = function() {
File.find({}, function(err, res) {
if (err) console.log(err);
else {
return res.json();
}
});
};
To:
findAll = (req, res) => {
File.find({}, function(err, result) {
if (err) console.log(err);
else {
return res.json({ result });
}
});
};

Express API DELETE

I am trying to add DELETE to my api, but am getting a 404: Not Found for everything I try. All of the GET and POST methods work. This is using the "Points" model that contains points, each with a unique id. I am trying to add a call to delete a point by its id.
Action
export function deletePointById(identifier) {
return dispatch => {
return axios.delete('/api/points/' + identifier)
}
}
Route for DELETE (doesn't work)
router.delete('/:identifier', (req, res) => {
Points.remove({
id: req.params.identifier
}), function (err, user) {
if (err) {
return res.send(err);
}
res.json({ message: 'Deleted' });
};
});
Here is an existing GET that works fine
Action
export function getPointsBySession(session){
return dispatch => {
return axios.get('/api/points/session/' + session)
}
}
Route for GET
router.get('/session/:session', (req, res) => {
Points.query({
select: ['id', 'number', 'quadrant', 'level', 'title', 'category'],
where: {sessionId: req.params.session}
}).fetchAll().then(point => {
res.json({ point });
})
});
It looks like your issue might be that theres an extra brace and semicolon ( };) in your code:
router.delete('/:identifier', (req, res) => {
Points.remove({
id: req.params.identifier
}), function (err, user) {
if (err) {
return res.send(err);
}
res.json({ message: 'Deleted' });
}; // <-- HERE
});
You also need to remove the semicolon on the line above the one I added the comment to.
It will look like this:
router.delete('/:identifier', (req, res) => {
Points.remove({
id: req.params.identifier
}), function (err, user) {
if (err) {
return res.send(err);
}
res.json({ message: 'Deleted' })
});

NodeJS MSSQL driver Passing data to a calling function

Working with an SQL Server in NodeJS, and I have confirmed that it's pulling the data, but I'm trying to pass the data back to a calling function.
Here's my call to the function that queries the database:
const dbq = require('./dbquery.js');
app.get('/:id', (req, res) => {
reqlog(`/${req.params.id}`);
var set = dbq.getPersonById(req.params.id);
console.log(set);
});
and here is the function inside dbquery.js:
qry.getPersonById = (id) => {
mssql.connect(sqlConfig).then(() => {
new mssql.Request().query(`select * from FNVPeople where IndivID=${id}`).then((record)=>{
console.log(record);
return record;
}).catch((err)=>{
console.log(err);
});
});
}
Should my call to the function look like this?
var dataset = await(dbq.getPersonById(req.params.id));
Because of Async nature.
Try for the following:
const dbq = require('./dbquery.js');
app.get('/:id', (req, res) => {
reqlog(`/${req.params.id}`);
dbq.getPersonById(req.params.id, function(err, res){
console.log(res);
});
});
qry.getPersonById = (id, callback) => {
mssql.connect(sqlConfig).then(() => {
new mssql.Request().query(`select * from FNVPeople where IndivID=${id}`).then((record)=>{
console.log(record);
callback(null, record);
}).catch((err)=>{
console.log(err);
});
});
}
You should return the promise to the client to deal with (note two additional returns):
qry.getPersonById = (id) => {
return mssql.connect(sqlConfig).then(() => {
return new mssql.Request().query(`...`)
.then((record)=>{
console.log(record);
return record;
})
.catch((err)=>{
console.log(err);
});
});
}
Then, the client deals with the promise
app.get('/:id', (req, res) => {
reqlog(`/${req.params.id}`);
dbq.getPersonById(req.params.id).then( set =>
console.log(set);
);
});
By rewriting promises to async/await you could even have
qry.getPersonById = async (id) => {
try {
await mssql.connect(sqlConfig)
var record = await new mssql.Request().query(`...`);
console.log(record);
return record;
}
catch (err) {
console.log(err);
}
}
and
app.get('/:id', async (req, res) => {
reqlog(`/${req.params.id}`);
var set = await dbq.getPersonById(req.params.id);
console.log(set);
});

Resources