node.js blocking, non-blocking issue in for statement - node.js

How can I save all of the json into my mongoldb?
Strangely, only the first value is stored every time.
It might be blocking/non-blocking issue.
json = {
["name":"Karl","id":"azo0"],
["name":"Robert","id":"bdd10"],
["name":"Joan","id":"difj90"],
["name":"Hallyn","id":"fmak88"],
["name":"Michael","id":"vma91"]
};
for(var i = 0; i < json.length; i++){
id = json[i].id;
name = json[i].name;
var ctx = {"id":id,"name":name};
db.json_db.count(ctx).exec(function(err, count) {
if(count < 1){
var model = new User({
"name":json[i].name,
"id":json[i].id
});
model.save(function(){
console.log("ok"+i);
});
}
});
};
After inserting, all of datas are filled with ["name":"Karl","id":"azo0"]
To check out console.log("ok"+i), it prints always "ok0" not "ok1", "ok2", "ok3"... etc..
How can I prevent this issue?

Incase you're using Async package, this is an best way to solve your problem...
async.eachSeries(json, (item, done) => {
let user = new User(
{
"name":json[i].name,
"id":json[i].id
},
(err, user) => {
if(err){
// handle err
}
return done();
}
);
});

.exec() tells me you're using Mongoose. So your loop can rewritten as:
const json = [
{name: "Karl", id: "azo0"},
{name: "Robert", id: "bdd10"},
{name: "Joan", id: "difj90"},
{name: "Hallyn", id: "fmak88"},
{name: "Michael", id: "vma91"}
];
for (const item of json) {
const count = await db.json_db.count(item).exec()
if (!count) {
await new User(item).save()
}
}
Error handling omitted.
See http://exploringjs.com/es2016-es2017/ch_async-functions.html

Related

My save data to MongoDB not functioning, is it because my searching is wrong?

I'm trying to make a comparison function. If the value that I search is not exist, the new value will be save to the database. But all I get is 0 new data found. So the system decides to not save the data. Is my searching wrong?
This is my code:
var count = 0;
for (var t = 1; t < 151; t++) {
var searching = JobsSchema.find({ jobName: name[t], company: company[t] })
if (searching == null) {
count = count + 1;
var newJobs = new JobsSchema({
"jobName": name[t],
"country": country[t],
"company": company[t],
"jobType": type[t],
"salary": salary[t],
"skills": skills[t],
"jobDesc": desc[t],
"jobReq": req[t],
"jobResponsibility": resp[t],
"industry": industry[t],
})
newJobs.save(function (err, result) {
if (err) {
console.log(err);
}
})
}
}
console.log(count + " new data found.");
You should await your find function.
Also, change it to findOne to return a single instance of the JobsSchema and await the save call as well.
Finally you will need to wrap the code into an async function:
const saveData = async () => {
var count = 0;
for (var t = 1; t < 151; t++) {
var searching = await JobsSchema.findOne({
jobName: name[t],
company: company[t],
});
if (!searching) {
count = count + 1;
var newJobs = new JobsSchema({
jobName: name[t],
country: country[t],
company: company[t],
jobType: type[t],
salary: salary[t],
skills: skills[t],
jobDesc: desc[t],
jobReq: req[t],
jobResponsibility: resp[t],
industry: industry[t],
});
await newJobs.save();
}
}
console.log(count + ' new data found.');
};
saveData();

Iterate dataArray to create an object is not happening

How can I parse the incoming nomData data array and store those values into an object along with userEmail ? Somehow below code is not working, could someone pleas advise the issue here.
Expected database columns values:
var data = { useremail: userEmail, nomineeemail: email, nomineename: name, nomineeteam: team, reason: reason }
server.js
app.post('/service/nominateperson', async (req, res) => {
try {
const userEmail = req.body.userEmail;
const nomData = req.body.nomRegister;
const formData = {
useremail: userEmail,
nomineeemail: {},
nomineename: {},
nomineeteam: {},
reason: {}
}
const newArray = nomData.map(item => {
formData.nomineeemail = item.email;
formData.nomineename = item.name;
formData.nomineeteam = item.team;
formData.reason = item.reason;
});
var data = { useremail: userEmail, nomineeemail: email, nomineename: name, nomineeteam: team, reason: reason }
// Ideally I should get nomData
//items parsed create an data object and pass that into bulkCreat() method:
const numberOfNominations = await NominationModel.count({where: {useremail: userEmail}});
if (numberOfNominations <= 3) {
const nominationData = await NominationModel.bulkCreate(data);
res.status(200).json({message: "Nomination submitted successfully !"});
} else {
res.status(202).json({message: "Nomination limit exceeded, please try next week !"});
}
} catch (e) {
res.status(500).json({fail: e.message});
}
});
So i assume nomData is an array containing multiple nominations. So if you want to bulkCreate with data you should pass an array instead of an object.
const data = nomData.map(item => ({
useremail: userEmail,
nomineeemail: item.email,
nomineename: item.name,
nomineeteam: item.team,
reason: item.reason
}));
...
await NominationModel.bulkCreate(data)

How to count the amount of objects by id in a list using parse

I've done the count with a single object using promises but when I tried to do it with a list of objects it displayed the counted object with the same number of objects in the list.
I already display the vehicles but I need to display their routes.
Here's the code for getting the list of vehicles
const Car = Parse.Object.extend('Vehicle');
const query = new Parse.Query(Car);
//car search
app.get('/car-search', async function (req, res) {
const VehicleInfo = [];
query.notEqualTo("Route", null);
query.notEqualTo("PassengerAmount", null);
try {
const result = await query.find();
result.forEach(vehicle => {
VehicleInfo.push({
VehicleID: vehicle.id,
VehicleImage: vehicle.get("Image")._url,
VehicleName: vehicle.get('Name'),
Description: vehicle.get('Description'),
Price: vehicle.get('Price'),
Rating: vehicle.get('Rating'),
Route: vehicle.get('Route'),
PassengerAmount: vehicle.get('PassengerAmount')
});
});
res.render('car-search', {
title: 'Vehiculos',
VehicleData: VehicleInfo
});
} catch (error) {
throw error;
}
});
Here's the code to do the count, I use this in another page to display only a single vehicle.
for (let i = 0; i < result.length; i++) {
let FoundVehicles = result[i];
let CountRoute = query.count(FoundVehicles.get('Route'));
let Count = CountRoute.then(function(data){
return data;
})
let RouteAmount = (await Count).valueOf(FoundVehicles.get('Route'))
VehicleInfo.push({
VehicleName: FoundVehicles.get('Name'),
Description: FoundVehicles.get('Description'),
Price: FoundVehicles.get('Price'),
Rating: FoundVehicles.get('Rating'),
Route: RouteAmount,
PassengerAmount: FoundVehicles.get('PassengerAmount')
});
}
This is what the console displays in the list if I use the count there
list of counted routes
This is an example of what I'm trying to do
enter image description here
The "Reseñas" part (reviews) one of the cars should have 2, the other 3 and so on
Try:
for (let i = 0; i < result.length; i++) {
let FoundVehicles = result[i];
let RouteAmount = FoundVehicles.get('Route').length;
VehicleInfo.push({
VehicleName: FoundVehicles.get('Name'),
Description: FoundVehicles.get('Description'),
Price: FoundVehicles.get('Price'),
Rating: FoundVehicles.get('Rating'),
Route: RouteAmount,
PassengerAmount: FoundVehicles.get('PassengerAmount')
});
}

Synchronising Lodash and mongoose query in nodejs

I am trying to accomplish synchronisation in Mongoose query inside a _.each lodash function like this -
let commentContainer = [];
let comments = {..} //json object having comments
_.each(comments, comment => {
User.findOne({_id: comment.createdBy}).exec()
.then(function(commentor){
var c = {
text: comment.text,
votes: comment.votes.length,
commentor: {
name: commentor.name,
profilePhoto: commentor.profilePhoto,
id: commentor._id
}
}
commentContainer.push(c);
});
});
}
console.log(commentContainer); //it shows []
How can I achieve it, I tried using setTimeout function by giving a delay but it does not seems a valid procedure.
modify your code like this way:
let fun = async() => {
let commentContainer = [];
let comments = {..} //json object having comments
await _.each(comments, comment => {
User.findOne({_id: comment.createdBy}).exec()
.then(function(commentor){
var c = {
text: comment.text,
votes: comment.votes.length,
commentor: {
name: commentor.name,
profilePhoto: commentor.profilePhoto,
id: commentor._id
}
}
commentContainer.push(c);
});
});
}
console.log(commentContainer); //it shows []
}
make your function async and use await keywoed when you need to wait for the process to complete before next iteration
It's because Node.js is asynchronous.You should use async/await or promise or callback when you are dealing with non-blocking call like DB-call or Http client call.
let comments = {..} //json object having comments
console.log(findUSer(comments)); // print result
async function findUSer(comments){
let commentContainer = [];
await _.each(comments, comment => {
User.findOne({_id: comment.createdBy}).exec()
.then(function(commentor){
var c = {
text: comment.text,
votes: comment.votes.length,
commentor: {
name: commentor.name,
profilePhoto: commentor.profilePhoto,
id: commentor._id
}
}
commentContainer.push(c);
});
});
}
return commentContainer;
}

Sequelize Transaction inside forEach loop

I'm trying to use transaction inside forEach loop using async/await syntax of Node 7.0+
When I try to print committed transaction response in console, I'm able to see the values but those same values are not committed in to DB.
Below is the code :
documentInfo.forEach(async (doc) => { // array of documentInfo
var frontImgName = await module.exports.uploadImage(docFiles, doc.front, req, res )
var backImgName = await module.exports.uploadImage(docFiles, doc.back, req, res )
var checkKycDoc = await KYCDocument.findOne({
where: {
kyc_id: checkUserKyc.dataValues.kyc_id,
user_id: checkUserKyc.dataValues.user_id
}
})
if (checkKycDoc) { //update
var updateDocument = await KYCDocument.update({
document_name: doc.document_name,
front_image: frontImgName,
back_image: backImgName
}, {
where: {
kyc_id: checkUserKyc.dataValues.kyc_id,
user_id: checkUserKyc.dataValues.user_id
},
}, {transaction})
log('updateDocument', updateDocument.dataValues)
} else { // insert
var newKycDocument = await new KYCDocument({
kyc_id: checkUserKyc.dataValues.kyc_id,
user_id: checkUserKyc.dataValues.user_id,
document_name: doc.document_name,
front_image: frontImgName,
back_image: backImgName,
status: true
}, {transaction})
log('newKycDocument', newKycDocument.dataValues)
}
if (rowCount === documentInfo.length) {
await transaction.commit() // transaction is printed on this line
log('KYC has been uploaded successfully')
helpers.createResponse(res, constants.SUCCESS,
messages.KYC_UPLOAD_SUCCESS,
{'error': messages.KYC_UPLOAD_SUCCESS}
)
} else {
rowCount++
}
})
The issue was in the create method.
To resolve the issue I had to create a new row using:
var newKycDocument = await KYCDocument.create({
kyc_id: checkUserKyc.dataValues.kyc_id,
user_id: checkUserKyc.dataValues.user_id,
document_name: doc.document_name,
front_image: frontImgName,
back_image: backImgName
}, {transaction})
I was missing the .create method.

Resources