Update all Rows and then send response sequelize - javascript

I'm Pretty new doing this kind of tasks in Node. I have a POST method (express) wich recive an array of objects like:
[{F1:'123',F2:'a',F3:'b',F4:'Z'},
{F1:'124',F2:'a',F3:'b',F4:'Z'},
{F1:'125',F2:'a',F3:'b',F4:'Z'},
{F1:'126',F2:'a',F3:'b',F4:'Z'},]
Then, i need do an Update for every object in the array.
Im using sequelize :
MODEL.update(
{
att4: art['F4'],
},
{
where:{
att1: {$eq: art['F1']}
}
}).then(function(result)
{
res.status(200).send();
}).catch(function(err)
{
res.status(500).send(err);
})
And this work for 1 object.
But i need the following: WHEN ALL THE UPDATES are processed, then send a response.
I try with
req.body.forEach(function(o)
{
updateO(o)
},this);
and in updateO(o) do the Model.Update , but i don't achieve the needed result.
Sorry for the bad english, hope can understand me and thank's for your help.

Read about promises, all Sequelize's functions return promises, you can handle multiple querying through Promise.all
var objects = req.body;
Promise.all(objects.map(object=>{
return MODEL.update({att4: object.F4},{where:{att1: object.F1});
})).then(function(result){
res.status(200).send();
}).catch(function(err){
res.status(500).send(err);
})

Related

Node: run 2 sql queries at the same time

I have a simple api to communicate with my mobile app and i have some updates to do.
I want to make 2 updates at the same function (or th same route) but i dont know if its possible.
Here is the dboperation part:
async function updateCusto() {
try {
let pool = await sql.connect(config);
let updateCusto = await pool.request()
.input('input_parameter1', sql.Int, CodOS)
.input('input_parameter2', sql.Int, CodProduto)
.query("update osproduto set custounit=produto.precocusto, valorunitario=produto.precosugerido from OSProduto INNER JOIN Produto ON OSProduto.CodProduto = Produto.Codigo where codproduto=#input_parameter2 and codos=#input_parameter1")
.query("Update OSProduto set sub=qtde*valorunitario where codos=#input_parameter1") //the second one, doenst work
return updateCusto.recordsets;
}
catch (error) {
console.log(error);
throw error;
}
}
and here is the route part:
router.route("/updateCusto").post((request, response) => {
CodOS = request.body.CodOs;
CodProduto = request.body.CodProduto;
dboperations.updateCusto(CodOS, CodProduto).then(result => {
console.log(result);
response.json("Update ok!");
})
.catch(error => response.json({ error }))
})
How can i do this? Is there a way to run the 2 updates on the same operation? Or do i need to create another operation to use on the same route, after the first update is made (and if so, how can i do that?).
It's definitely possible, in fact I would do it as a transaction, this way if one of the queries fails a rollback would be made in order to preserve the state of your database.
Here are my suggestions:
Read about database transactions
Replace pure SQL with an ORM such as Sequelize or KnexJS, it will help you to prevent errors by making queries calling methods such as await OsProduto.update({ where: { id: 0 }}, newData);

'TypeError: Converting circular structure to JSON' with Express

I use NodeJS and Express for my project and set it when the user login to index will keep the session value.
req.session.user
{ adminID: 3, username: 'admin', password: 'admin' }
And I want to get data from MYSQL so I use Knex like this.
router.get('/profile/user/me', (req, res, next) => {
let user = req.session.user;
if(user) {
try {
let me = req.session.user.adminID;
let info = knex('admin_account').where('adminID', `%${me}%`)
res.json(info)
} catch (e) {
console.log(e);
}
res.sendFile(path.join(__dirname + '/../public/personal_information.html'));
return;
}else{
res.redirect('/');
}
});
In my opinion, I think that if we are finished logging in, we will have a req.session.user I will use it to get data together with Knex.
req.sessions.user and info may have the same value but arent the same type you should, first check the value of your variable info console.log(info), there is a chance that you might need to json.parse() it or json.stringify() it if you want to send it as a response.
You need to execute the query builder and wait for result before returning:
knex('admin_account').where('adminID', me)
.then(info => {
res.json(info)
})
.catch(err => {
console.log(e);
});
And you don't need % wildcards unless you are doing loose string comparison with like operator.
One more thing about the code is that you seem to try to return res.json and also res.sendFile(path.join(__dirname + '/../public/personal_information.html')) at the same time, which doesn't make sense.

Using Bluebird Promisifyall with Mongoose

I'm using mongoose with Bluebird promisifyall as follows:
var mongoose = require('bluebird').promisifyAll(require('mongoose'))
I want to retrieve a document from mongo using where as follows:
// Gets a list of Posts
exports.index = function(req, res) {
console.log(req.query);
Post.findAsync()
.whereAsync({author: req.query.id})
.execAsync()
.then(function(entity) {
if (entity) {
res.status(statusCode).json({
status_code: statusCode,
data: entity
});
}
})
.catch(function(err) {
res.status(200).json({
status_code: statusCode,
message: 'error occured',
errors: err
});
});
};
But it just hangs, I'm I doing something wrong?
Would appreciate any help on using promisifyall from bluebird with mongoose, thanks :)
find and where are not asynchronous, they don't take callbacks. So don't use the …Async variant of them - you don't expect them to return a promise, you want a mongoose query object.
Try
Post.find().where({author: req.query.id}).execAsync()
.then(…)
.…
Btw, your request does hang if entity is falsy, you never write a response in that case. Consider adding an else with a throw new Error("no entity").

Node.js, MongDB (Mongoose) - Adding to data retrieved.

I currently have the following code:
User.find({ featuredMerchant: true })
.lean()
.limit(2)
.exec(function(err, users) {
if (err) {
console.log(err);
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
_.forEach(users, function(user){
_.forEach(user.userListings, function(listing){
Listing.find({
user: user
}).populate('listings', 'displayName merchantName userImageName hasUploadedImage').exec(function(err, listings){
user.listings = listings;
});
});
});
res.jsonp(users);
}
});
As you can see I am trying to add the retrieved listings to each 'user' in the 'users' lean object that I have returned. If I do a console.log(user) inside the Listing.find exec method after adding 'user.listings = listings', the result is as I would expect; a user object with a listings property, with this listing property containing all the listings retrieved.
However, if I console.log the 'users' object, the listings for each user cannot be found.
I'm pretty sure I'm doing something stupid here, but I really cannot work out what. Any help would be greatly appreciated. Thank you!
you right about stupid thing !
No offense, I think this is a common mistake :)
_.forEach(users, function(user){
_.forEach(user.userListings, function(listing){
Listing.find({
user: user
})
.populate('listings', 'displayName merchantName userImageName hasUploadedImage')
.exec(function(err, listings){
user.listings = listings;
});
});
});
// Listing.find inside foreach hasn't finish yet
// I suppose it's always an asynchronous call
res.jsonp(users);
Maybe you can fix it using promises. This an example with q library.
var promises = [];
_.forEach(users, function(user){
_.forEach(user.userListings, function(listing){
var deferred = q.defer();
promises.push(deferred);
Listing.find({
user: user
})
.populate('listings', 'displayName merchantName userImageName hasUploadedImage')
.exec(function(err, listings){
user.listings = listings;
deferred.resolve(user);
});
});
});
q
.all(promises)
.done(function(allUsers){
// Do what you want here with your users
res.jsonp(allUsers);
});
Check this and don't hesitate to fix it because I can't test it.
Thank you both for your input. It's truly appreciated. I managed to solve this an easier way which now I come to think of it is pretty obvious - but hey we live and learn. Basically, my 'userListings' model field was an array of Object Id's and I wanted to add the physical listings from the listings model into the data returned. The following code did the trick for me.
exports.findFeaturedMerchants = function(req, res, next) {
User.find({ featuredMerchant: true })
.populate('userListings')
.limit(2)
.exec(function(err, data) {
_.forEach(data, function(user){
Listing.populate(user.userListings, '', function(err, user){
if (err) {
console.log(err);
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
}
});
});
console.log(data);
res.jsonp(data);
});
};
I simply had to populate each userListings object into the user, by using the populate function twice - once for the user and another time for each listing. I was finding it tricky to get my head around - probably because I didn't understand how the populate function worked exactly, but there we go :)
Jamie

Access API endpoints in MEANjs from server controller

so i have this problem i am working on 'following' feature in my application. What's important, i have two models:
Follows and Notifications
When I hit follow button in front-end I run function from follow.client.controller.js which POSTs to API endpoint /api/follows which corresponds to follow.server.controller.js and then update action on Follows model is performed - easy. AFAIK thats how it works (and it works for me).
But in follows.server.controller.js I want also invoke post to API endpoint at /api/notifications which corresponds to notifications.server.controller.js but I can't find a proper way to do that. Any help will be appreciated.
I don't want another call from front-end to add notification because it should be automatic = if user starts following someone, information is saved in both models at once.
You can add middleware in your server route.
app.route('/api/follows')
.post(notification.firstFunction, follows.secondFunction);
And now add 2 methods in your contollers. First makes the call to db and add's some result's data to request object which will be forwarded to second method.
exports.firstFunction= function(req, res, next) {
Notification.doSometing({
}).exec(function(err, result) {
if (err) return next(err);
req.yourValueToPassForward = result
next(); // <-- important
});
};
exports.secondFunction= function(req, res) {
//...
};
Or you can make few database calls in one api method, joining this calls with promises. Example:
var promise = Meetups.find({ tags: 'javascript' }).select('_id').exec();
promise.then(function (meetups) {
var ids = meetups.map(function (m) {
return m._id;
});
return People.find({ meetups: { $in: ids }).exec();
}).then(function (people) {
if (people.length < 10000) {
throw new Error('Too few people!!!');
} else {
throw new Error('Still need more people!!!');
}
}).then(null, function (err) {
assert.ok(err instanceof Error);
});

Categories

Resources