Mongoose updating and fetching in the same request - mern

I have the following mongoose "update" path:
app.put('/update', async (req, res) => {
const newTaskName = req.body.todoName
const newDays = req.body.days
const id = req.body.id
try {
await TodoModel.findById(id, async (err, updatedTodo) => {
updatedTodo.todoName = newTaskName
updatedTodo.daysToDo = newDays
await updatedTodo.save()
res.send("updated")
})
} catch(err) {
console.log(err)
}
})
Separately I have a path that returns all data from the Mongo table:
app.get('/read', async (req, res) => {
TodoModel.find({}, (err, result) => {
if (err) {
res.send(err)
}
res.send(result)
})
})
How can I both update and send back the full updated list within the response?
Separate question, not necessary to answer, but would be nice - perhaps this approach is all wrong? some background:
In my MERN app I am calling to add an item to a list and then want to immediately render the updated list as currently read from the database, since I don't want to assume the insertion was successful
I tried using some asynchronous workarounds with no luck

Fixed!
Upon further inspection of Mongoose documentation, I found that by using the findOneAndUpdate method instead of findById, I am able to utilize a callback that will return the updated item:
app.put('/update', async (req, res) => {
const id = req.body.id
let updateSet = req.body
delete updateSet.id
try {
ShoppingModel.findOneAndUpdate({ _id: id }, { $set: updateSet }, { new: true }, (err, doc) => {
if (err) return console.log(err)
res.send(doc)
})
} catch (err) {
console.log(err)
}
})

Related

Nodejs Mysql asynchronous

I'm trying to return my users list from my Mysql database through this endpoint.
The problem is that it return "undefined".
Do you know how to solv this?
Thx in advance :)
app.get("/users", async (req, res) => {
users = await query_my_users_from_db()
// Got "users = undefined" here
console.log(users)
return JSON.stringify(users)
})
async function query_my_users_from_db() {
var users = await db.query("SELECT * FROM `users`", function (err, result) {
if (err) throw err
users = Object.values(JSON.parse(JSON.stringify(result)))
return users
})
}
Since db.query is callback based, you should change your code into:
function query_my_users_from_db(callback) {
db.query("SELECT * FROM `users`", callback)
}
remove all the async\await since you are not using any promises!
then define your callback
const usersHandler = (err, result) => {
... do what you want with your users ...
}
and use it like this:
query_my_users_from_db(usersHandler)
Another option is to use some promise-based wrapper package for MySQL, there is plenty or use node util.promisify() (https://www.geeksforgeeks.org/node-js-util-promisify-method/) and then use async\await and remove the callback altogether.
Hope that it helps
I used this and it's working like a charm.
db.promise = (sql, params) => {
return new Promise((resolve, reject) => {
db.query(sql, params, (err, result) => {
if (err) {
reject(new Error())
} else {
resolve(result)
}
})
})
}
async function connection(query) {
const result = await db.promise(query)
return result
}
app.get("/users", async (req, res) => {
users = await connection("SELECT * FROM `users`")
return users
})

Axios Chaining. Cloudinary Upload -> Express -> MSQL save

My second axios call requires const { secure_url } = res.data from the first axios call.
I use the secure url to store in my database with another axios call.
await axios.post(details.upload, formData, {
onUploadProgress: ProgressEvent => {
setUploadP(parseInt(Math.round((ProgressEvent.loaded * 100) / ProgressEvent.total)))
setTimeout(() => setUploadP(0), 3000);
}
})
.then((res) => {
const { secure_url } = res.data;
axios.post('https://foodeii.herokuapp.com/api/insertRecipe', { values: inputValue, userID: props.userID, img: secure_url }).then((response) => {
console.log('Recipe added successfully.')
goBack();
})
})
.catch((err) => {
console.log(err);
})
The second axios call works fine with uploading the data, but I get a timeout, the console log doesn't fire either. My Express insert function is really small so I do not understand why it timeouts.
// INSERT
app.post('/api/insertRecipe', (req, res) => {
const data = req.body.values;
const uID = req.body.userID;
const img = req.body.img;
const sqlInsert = "INSERT INTO recipes (uID, NAME, INGREDIENTS, INSTRUCTIONS, IMAGE) VALUES (?,?,?,?,?)";
db.query(sqlInsert, [uID, data.theName, data.ingredients, data.instructions, img], (err, result) => {
console.log(err);
});
})
My Server runs on Heroku, while the React frontend is on netlify.
The server error is 'code=H12' when the timeout occurs.
Thank you

How do I fetch just one object from the mySQL database?

I want to get and res.send user_image from the table. I tried to use attributes: ['user_image'], but it does not work. Is there any other keyword or style to fetch just one object?
const router = require('express').Router();
const db = require('../models');
router.get('/image/:user_id', (req, res) => {
try {
db.Customer.findAll({
where: {
user_id: req.params.user_id,
attributes: ['user_image'],
},
}).then((user) => res.send(user));
} catch (err) {
res.status(500).json(err);
}
});
module.exports = router;

Returning undefined from mySQL

I know the database is connecting with the code as, when i console.log(res) with the code below it is returning the correct data,
const orm={
selectAll(){
connection.query('SELECT * FROM burgers', (err,res) => {
if (err) throw err;
console.log(res)
return res;
});
},
Yet when i console.log(burgers) from this function in the code below it is returning an undefined
app.get(`/`, function (req, res) {
const burgers = orm.selectAll();
console.log(burgers)
res.render(`index`, burgers);
});
I understand this may be a very simple answer but i personally just cannot work it out any help is welcomed.
selectAll is using a callback style method inside it. You can not get the response syncronously. You need to either pass the callback to selectAll or change it to use promise like this
function selectAll() {
return new Promise((reoslve, reject) => {
connection.query("SELECT * FROM burgers", (err, res) => {
if (err) {
reject(err);
}
reoslve(res);
});
});
}
You can then use it like this
app.get(`/`, function async (req, res) {
const burgers = await selectAll();
console.log(burgers)
res.render(`index`, burgers);
});
Your selectAll method will not return any value.
query get an lambda callback function as second parameter AND query is asyncron
One way is to return an Promise from selectAll
const orm = {
selectAll(callback) {
return new Promise((resolve, reject) => {
connection.query('SELECT * FROM burgers', (err, res) => {
if (err) {
reject(err);
} else {
resolve(res)
}
})
})
},
Than you can get your result:
app.get(`/`, function (req, res) {
orm.selectAll().then( burgers => {
console.log(burgers)
res.render(`index`, burgers);
});
});

Convert MySQL update query into sequelize query

UPDATE `users` SET tempToken=tempToken-"5" WHERE `id`="1"
How can I write this query into sequelize query.
For an async function, this is how you would do it, assuming you've set up your User model:
myFunction: async (req, res) => {
var tempToken = req.body.tempToken // Put whatever your data source is here for tempToken
var newValue = tempToken - 5
try {
await User.update({
tempToken: newValue
},
{
where: [{
id: 1
}]
})
res.status(200).send();
}
catch (error) {
res.status(500).send(error);
}
}
or
myFunction: async (req, res) => {
try {
const user = User.findOne({
where: {
id: 1
}
})
await user.update({
tempToken: user.tempToken - 5
})
res.status(200).send();
}
catch (error) {
res.status(500).send(error);
}
}
Also, don't forget to 'require' the user model in the .js file that you use this function in.