Node js crash with multiple update (mongoose) - node.js

I use this code in my controller to update one or more projects in my DB.
update: function(req, res) {
var ids = new Array();
for(var i =0;i<req.body.data.length;i++){
ids.push(req.body.data[i]._id);
}
ids.forEach(function (id,index) {
dayModel.findOne({_id: id}, function(err, day){
if(err) {
console.log("error");
}
if(day) {
day.worker = req.body.data[index].lav_mail ?
req.body.data[index].lav_mail : day.worker;
day.date = req.body.data[index].date ?
req.body.data[index].date : day.date;
day.hours = req.body.data[index].ore ?
req.body.data[index].ore : day.hours;
day.project = req.body.data[index].progetto ?
req.body.data[index].progetto : day.project;
day.activity = req.body.data[index].attività ?
req.body.data[index].attività : day.activity;
try {
day.save(function(err, day){
//return res.json(day);
});
}catch(ex){
console.log(ex.stack);
}
}
});
});
}
Then in the router
router.put('/', function(req, res) {
dayController.update(req, res);
});
When a user makes a lot of calls, NodeJS crashes.
Do you have any suggestion?

Although you can use async module there is a way without it.
Following code will update one record after another and when done it will return array of days.
update: function(req, res) {
var days = [];
updateOne();
function updateOne(){
// get one data object from array
var data = req.body.data.pop();
dayModel.findOne({_id: data.id}, function(err, day){
if(err) {
console.log("error");
}
if(day) {
...
day.save(function(err, day){
days.push(day);
// if no more data then return
if(!req.body.data.lenght) return res.json(days);
// otherwise update another one
updateOne();
});
}
});
}
}

Related

passing name in url in nodejs

The code which i have written takes id from url and then gives me the output.
api?category=4556 here 4556 is the id.
I have one Products controller having
product_name
price
category_id:i am passing category id manually from category generated.
and in category controller i have category_name.
here i want to get in this way
api?category=games
is there any way to do so.
exports.getProducts = function(req, res) {
// Use the Prod model to find all products
/*
Prod.find(function(err, prods) {
if (err)
res.send(err);
res.json(prods);
next();
});
*/
var cat=req.query.category;
var condition = {};
if (cat) {
condition.cat_id = cat;
}
Prod.find(condition).then(function(cat) {
res.json({cat});
})
.catch((err) => {
console.log('error', err);
res.status(500).send();
});
};
This code checks for the products having cat_id similar to the id provided by url as ?category=4556
i want to check it as ?category=games ,
if there is some way please help it would be great pleasure.thanks in advance
I found one answer and this really works using populate
var cat=req.query.category;
var condition = {};
if (cat) {
condition.cat_id = cat;
}
Prod.find(condition).populate('cat_id').then(function(cat) {
res.json({cat});
})
.catch((err) => {
console.log('error', err);
res.status(500).send();
});
};
and did a bit change in Schema
var ProductSchema=new mongoose.Schema({
name:String,
category:String,
price:Number,
cat_id:{
type : mongoose.Schema.Types.ObjectId,
ref : 'Cat'
}
});
// Export the Mongoose model
module.exports=mongoose.model('Prod',ProductSchema);
You will have to retrieve first the category ID from the name that was supplied in the query.
When no category with the supplied name is found, you may want to return an empty products dataset. I also make the assumption that category name are unique.
Example :
exports.getProducts = function(req, res) {
var categoryName = req.query.category;
var condition = {};
if (categoryName) {
condition.name = categoryName;
}
Category.find(condition).then(function(categories) {
if(categories.length === 0) return {}
return Product.find({ category_id: categories[0].id })
}).then(function(products) {
res.json(products);
}).catch((err) => {
console.log('error', err);
res.status(500).send();
});
};
If you want to find correspond to your category name rather than your id then you have to do only one change. Fetch category name from request query (as currently you are fetching id from request query). Rest your code will be same.
I am thinking that your category name is unique also.
exports.getProducts = function(req, res) {
// Use the Prod model to find all products
/*
Prod.find(function(err, prods) {
if (err)
res.send(err);
res.json(prods);
next();
});
*/
var cat=req.query.categoryName;
var condition = {};
if (cat) {
condition.cat_Name = cat;
}
Prod.find(condition).then(function(cat) {
res.json({cat});
})
.catch((err) => {
console.log('error', err);
res.status(500).send();
});
};
Hope it will work for you.
Thanks.

node.js creating custom module with function to return a value

I've never had to do this before. I've created myModule.GetRecord() and I can see the recordset successfully has the expected record.
However, ret in router.get() is undefined.
I believe because I need to catch the returned value in a callback.
I don't know how to define this module/function for a callback (if that is what I am appropriately looking to do) or how to call this function for a callback.
I've tried a few different things i.e. the typical GetRecord(ret, function () { ... }); But didn't see anything that appeared to work. And I read a bunch on the line but didn't find what I believe I'm looking for.
I really don't care to much about how I get there, but all I'm really trying to do is have mm.GetRecord()'s returned value in some usable form in the router.get()
--- myModulefile.js ---
'use strict';
module.exports = {
GetRecord: function (id) {
var sql = require('mssql');
sql.connect({ user: 'sa', ... database: 'name' }, function (err) {
if (err) { console.log(err); return null; }
var cmd = new sql.Request();
cmd.query('select * from Records where id = ' + id, function (err, rs) {
if (err) { console.log(err); return null; }
if (rs.recordset.length > 0) {
console.log('rs[0]', rs.recordset[0]);
return rs.recordset[0];
} else {
return null;
}
});
});
}
};
--- myRouter.js ----
const express = require('express');
const router = express.Router();
const mm = require('../myModule');
router.get('/:id', function (req, res) {
var id = req.params.id;
var ret = mm.GetRecord(id)
console.log('ret', ret);
if (ret == null)
ret = JSON.stringify({ ID: -1, f1: 'unknown' });
res.send(ret);
});
module.exports = router;
Of course I find the answer after having placed the question on here.
GetRecord() has to be defined with a parameter that recieves the callback passed to it. And the callback paramater's variable fn is used in place of return
GetRecord: function (id, fn) {
var sql = require('mssql');
sql.connect({ user: 'sa', ... database: 'name' }, function (err) {
if (err) { console.log(err); fn(null); }
var cmd = new sql.Request();
cmd.query('select * from Records where id = ' + id, function (err, rs) {
if (err) { console.log(err); fn(null); }
if (rs.recordset.length > 0) {
console.log('rs[0]', rs.recordset[0]);
fn(rs.recordset[0]);
} else {
fn(null);
}
});
});
}
and
GetRecord(id, function(ret) {
console.log('ret', ret);
});

Trouble in using forEach function in node.js

I have been learning about q promises and tried to build up some mock APIs to implement its functionality,While doing so I came across the following error,
Enterprise.forEach is not a function
My API code is as follows,
var mongoose = require('mongoose');
var Enterprise = mongoose.model('Enterprise_gpy');
var q = require('q');
var displayEnterprise = function(req, res) {
function displayEnterpriseName() {
var deferred = q.defer();
Enterprise.forEach(function(err, doc) {
if (err) {
console.log('Error Finding Files');
deferred.reject(err);
} else {
var name = Enterprise.enterprise_name;
deferred.resolve({
name: name
});
}
return deferred.promise;
});
}
function displayEnterpriseEmail() {
var deferred = q.defer();
Enterprise.forEach(function(err, doc) {
if (err) {
console.log('Error Finding Files');
deferred.reject(err);
} else {
var email = Enterprise.enterprise_email;
deferred.resolve({
email: email
});
}
return deferred.promise;
});
}
q.all([
displayEnterpriseName(),
displayEnterpriseEmail()
])
.then(function(success) {
console.log(500, success);
})
.fail(function(err) {
console.log(200, err);
});
}
module.exports = {
displayEnterprise: displayEnterprise
}
In your code Enterprise is a mongoose schema so when you try to do loop using forEach then got
Enterprise.forEach is not a function
you can use forEach after Enterprise.find(). so use
Enterprise.find({}, function(err, docs) {
if (err) {
console.log('Error Finding Files');
deferred.reject(err);
} else {
var names = [];
docs.forEach (function(doc) {
var name = doc.enterprise_name;
names.push(name);// pushed in names array
//.....
});
deferred.resolve({
names: names
}); // return all names
}
});
instead of
Enterprise.find().forEach
and should use
var name = doc.enterprise_name; instead of var name = Enterprise.enterprise_name;
and
var email = doc.enterprise_email; instead of var email = Enterprise.enterprise_email;
forEach only works for arrays, and you're using it on a mongoose model.
try this instead:
Enterprise.find().exec(function(err, docs) {
docs.forEach(function(doc) {
// do something with all the documents
}
// do something outside the loop
})

How to find a record in MongoDB using Node.js

I am trying to find whether my collection has a record with profilename = john and if exists I return status success if else I return fail but in my case, it is returning success for both cases.I am new to node and mongo can any one help me.
My function,
exports.searchprofilename = function (req, res) {
var params = req.params;console.log(req.params.id);
var record= db.collection('profile');
record.find({profilename:params.id}, (err, result) => {
if (err){ return console.log(err)
}
if(!result){
data = {status:'success'};
} else{
data = {status:'profile name already exists'};
}
res.send(data);
});
};
If you are only checking if a record exists, you should be easily able to do it using db.collection.count() method and checking if the number of records = 0 or not.
https://docs.mongodb.com/manual/reference/method/db.collection.count/
Honestly, I am way new to mongodb and I still cannot grasp the idea of cursors which is the return type of db.collection.find() as per https://docs.mongodb.com/manual/reference/method/db.collection.find/
I cleared it by changing find({}) to findOne({}),Thank you every one.
If your query matches then it means you have record then return Success
exports.searchprofilename = function (req, res) {
var params = req.params;console.log(req.params.id);
var record= db.collection('profile');
record.find({profilename:params.id}, (err, result) => {
if (err){ return console.log(err)
}
// If record exist then return 'Success'
if(result.length>0){
data = {status:'success'};
} else{
data = {status:'profile name already exists'};
}
res.send(data);
});
};
I think in your case, req.params.id is a String for example '123', but in your mongodb profilename field is stored as an Number.
So you can try this:
change {profilename:params.id} to {profilename:parseInt(params.id)}
Try this
exports.searchprofilename = function (req, res) {
console.log("PARAMS",req.params.id);
var data = {};
profile.findOne( {profilename:req.params.id} , function (err, fetchDataObj) {
if (err) {
console.log(err)
return err;
} else {
data.status = 'success';
data.result = fetchDataObj;
return data;
}
}).lean(true)
});
Try to Debug. the type of result is array, so try to check the length of it:
if(result.length==0){
data = {status:'success'};
} else{
data = {status:'profile name already exists'};
}

Node.js - Query within a query, then render results using Express

I'm new to Node from the lands of C#, PHP and Python. I've been working days in many variations of the same problem - how can I retrieve a set of data, based on that data, retrieve another set, then render the results out. I've tried the method below, event based (client.on("row")) and the async module and I can't get any to produce the right results. In the end, I'd like to pass a projects object with tasks added to Express to render.
Could anyone help me out of this hole?
exports.index = function(req, res){
req.session.user_id = 1;
if (req.session == undefined || req.session.user_id == null || req.session.user_id < 0) {
res.redirect('/login');
} else {
var pg = require('pg');
var conString = "postgres://jason#localhost:5432/simpleproject";
var client = new pg.Client(conString);
client.connect(function(err) {
client.query("SELECT * FROM project", function(err, projects) {
for (var i=0; i<projects.rowCount; i++) {
var project = projects.rows[i];
client.query("SELECT * FROM task WHERE project_id="+projects.rows[i].id, function(err, subrows) {
if (subrows.rowCount > 0) {
project.tasks = subrows.rows;
console.log("adding tasks");
} else {
project.tasks = null;
}
if (i==projects.rowCount) {
console.log("rendering");
res.render('main', { title: 'My Projects', projects: projects });
}
});
}
if (err != null) { console.log(err); }
}
);
});
}
};
UPDATE: Meryn below provides a good solution to my issue, just to share that information, in the end, below his code with a little touch up to get it to operate: (thanks Meryn!)
var async = require('async');
exports.index = function(req, res){
req.session.user_id = 1;
if (req.session == undefined || req.session.user_id == null || req.session.user_id < 0) {
res.redirect('/login');
} else {
var pg = require('pg');
var conString = "postgres://jason#localhost:5432/simpleproject";
var client = new pg.Client(conString);
var addTasksToProject = function(projectRow, cb) { // called once for each project row
client.query("SELECT * FROM task WHERE project_id="+projectRow.id, function(err, result) {
console.log("tasks");
if(err) return cb(err); // let Async know there was an error. Further processing will stop
projectRow.tasks = result.rows;
cb(null); // no error, continue with next projectRow, if any
});
};
client.connect(function(err) {
client.query("SELECT * FROM project", function(err, projects) {
console.log("projects");
if (err) return console.error(err);
async.each(projects.rows, addTasksToProject, function(err) {
if (err) return console.error(err);
// all project rows have been handled now
console.log(projects.rows);
res.render('main', { title: 'My Projects', projects: projects.rows});
});
});
});
}
};
You need to familiarize yourself with asynchronous flow-control. It can be tricky because the async functions (postgres queries in this case) will execute right after another in the same turn of the event loop, while the results come trickling in in subsequent turns.
For your code example, this effectively means that i will be set to projects.rowCount-1 and project will be set to projects.rows[project.rowCount-1] almost instantly, while the queries have been queued up. They stay like this after the result for the queries come in. Not what you want.
The quickes solution is to use the Async library. https://github.com/caolan/async . This will handle the tedious bean-counting for you.
For this particular example, you'd replace the code within the client.connect callback with something like
addTasksToProject = function(projectRow, cb) { // called once for each project row
client.query("SELECT * FROM task WHERE project_id="+projectRow.id, function(err, result) {
if(err) return cb(err) // let Async know there was an error. Further processing will stop
projectRow.tasks = result.rows
cb(null) // no error, continue with next projectRow, if any
}
}
client.query("SELECT * FROM project", function(err, projects) {
if (err) return console.error(err)
async.each(projects.rows, addTasksToProject, function(err) {
if (err) return console.error(err)
// all project rows have been handled now
res.render('main', { title: 'My Projects', projects: project.rows});
})
}
Note that because how Javascript object references work, the objects part of the project.rows array will be actually modified in place. This wouldn't be the case if you'd actually try to assign a new value to the projectRow variable.

Resources