Increment field of another collection in mongodb - javascript

I created two collections,one for enterprise and another for employees,their schema is as follows,
var mongoose= require('mongoose');
var Enterprise= new mongoose.Schema({
name:{type:String},
email:{type:String},
sector:{type:String},
employees: {type:Number,default:0}
});
module.exports={
Enterprise:Enterprise
};
var mongoose = require('mongoose');
var employee = new mongoose.Schema({
enterprise:{type: String},
name:{type:String},
email:{type:String},
password:{type:String},
gender:{type:String},
});
module.exports = {
employee:employee
};
my add employee route,
var mongoose = require('mongoose');
var q = require('q');
var employee = mongoose.model('employee');
var enterprise = mongoose.model('enterprise');
var addEmployee = function(req, res) {
newEmployee = new employee();
newEmployee.enterprise = req.params.enterprise;
newEmployee.name = req.params.name;
newEmployee.email = req.params.email;
newEmployee.gender = req.params.gender;
function detailSave() {
var deferred = q.defer();
newEmployee.save(function(err, data) {
if (err) {
res.send(500);
console.log('couldnt save employee details');
deferred.reject({errmessage: 'couldnt save employee details', err: err});
} else {
res.send(200);
deferred.resolve({data: data});
}
});
return deferred.promise;
}
function incrementEmployee(doc) {
var deferred = q.defer();
enterprise.findOneAndUpdate({ 'name': doc.enterprise }, { $inc: { 'employees': 1 } },
function(err, num) {
if (err) {
deferred.reject({errmessage: 'couldnt incrementEmployee', err: err});
res.send(500);
console.log('couldnt incrementEmployee');
} else {
res.send(200);
deferred.resolve({num:num});
}
});
return deferred.promise;
}
detailSave()
.then(incrementEmployee)
.then(function(success) {
console.log('success', success);
res.json(200, success);
})
.fail(function(err) {
res.json(500, err);
})
.done();
};
module.exports = {
addEmployee: addEmployee
};
The problem is when I add an employee, the employees field in enterprise collection doesn't increment

I think your query is not working since doc.enterprise is null
On the basis of your comment.
Try to give your query like this {'name': doc.data.enterprise}
function incrementEmployee(doc) {
var deferred = q.defer();
enterprise.findOneAndUpdate({
'name': doc.data.enterprise
}, {
$inc: {
'employees': 1
}
},
function(err, num) {
if (err) {
deferred.reject({
errmessage: 'couldnt incrementEmployee',
err: err
});
res.send(500);
console.log('couldnt incrementEmployee');
} else {
res.send(200);
deferred.resolve({
num: num
});
}
});
return deferred.promise;
}

Related

MongoDB references with Node.js I can not populate

I want to show user's location information on the screen.
For Example:
name: "Andy" surname : "Carol" City : "Istanbul" Town : "Kadıkoy"
When I call the getuser function I want to display the City and Town name.
This is my code:
UserSCHEMA
// Model for the User
module.exports = (function userSchema() {
var Mongoose = require('mongoose');
var Schema = Mongoose.Schema;
var userSchema = new Schema({
name: {
type: String,
require: true
},
surname: {
type: String,
require: true
},
tel: {
type: String,
require: true
},
age: {
type: String,
require: true
},
mevki_id: {
type: String,
require: true
},
lok_id: [{
type: Mongoose.Schema.Types.ObjectId,
ref: 'locations'
}]
});
var collectionName = 'users';
var USERSCHEMA = Mongoose.Schema(userSchema);
var User = Mongoose.model(collectionName, USERSCHEMA);
return User;
})();
USERController
//This Controller deals with all functionalities of User
function userController() {
var User = require('../models/UserSchema');
// Creating New User
this.createUser = function (req, res, next) {
var name = req.body.name;
var surname = req.body.surname;
var tel = req.body.tel;
var age = req.body.age;
var mevki_id = req.body.mevki_id;
var lok_id = req.body.lok_id;
User.create({
name: name,
surname: surname,
tel: tel,
age: age,
mevki_id: mevki_id,
lok_id: lok_id
}, function (err, result) {
if (err) {
console.log(err);
return res.send({
'error': err
});
} else {
return res.send({
'result': result,
'status': 'successfully saved'
});
}
});
};
//Populateeee
this.getUser = function (req, res, next) {
User.find().populate('lok_id')
.exec(function (err, result) {
if (err) {
console.log(err);
return res.send({
'error': err
});
} else {
return res.send({
'USERS': result
});
}
});
};
return this;
};
module.exports = new UserController();
Location Schema
//Schema for Location
module.exports = (function LocationSchema() {
var Mongoose = require('mongoose');
var Schema = Mongoose.Schema;
var LocationSchema = new Schema({
userid: {
type: Mongoose.Schema.Types.ObjectId,
ref: 'users'
},
il: {
type: String,
require: true
},
ilce: {
type: String,
require: true
}
});
var collectionName = 'locations';
var LocationSCHEMA = Mongoose.Schema(schema);
var Location = Mongoose.model(collectionName, LocationSCHEMA);
return Location;
})();
Location Controller
//This Controller deals with all functionalities of Location
function locationController() {
var location = require('../models/LocationSchema');
// Creating New Location
this.createLocation = function (req, res, next) {
var userid = req.params.userid;
var il = req.params.il;
var ilce = req.params.ilce;
location.create({
userid: userid,
il: il,
ilce: ilce
}, function (err, result) {
if (err) {
console.log(err);
return res.send({
'error': err
});
} else {
return res.send({
'result': result,
'status': 'successfully saved'
});
}
});
};
// Fetching Details of Location
this.getLocation = function (req, res, next) {
location.find({}, function (err, result) {
if (err) {
console.log(err);
return res.send({
'error': err
});
} else {
console.log(result);
return res.send({
'location Details': result
});
}
});
};
return this;
};
module.exports = new locationController();
I already had a problem with model definition.
It was fixed by adding the third parameter to mongoose.model (the explicit collection name)
// Try to replace :
var collectionName = 'users';
var USERSCHEMA=Mongoose.Schema(userSchema);
var User = Mongoose.model(collectionName, USERSCHEMA);
// with:
var collectionName = 'users';
var USERSCHEMA=Mongoose.Schema(userSchema);
var User = Mongoose.model(collectionName, USERSCHEMA, collectionName);
the collectionName must be set either in the schema definition or in the model definition. for more details see here

Exporting Mysql Connection in nodeJS

In my database.js I have
var Mysql = require('Mysql');
var Jwt = require('jsonwebtoken');
var bcrypt = require('bcrypt');
var supersecretkey = 'JMDub_Super_Secret_key';
var config = require('./config');
var signupErrors = require('./Signuperrors.js');
var sucessMsg = require('./SucessMessages.js');
var App_errors = require('./error.js');
var query = require('./queryDB.js');
var connection = Mysql.createConnection({
"host": "******",
"user": "****",
"password": "***",
"database": "***"
});
connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
console.log('connected as id ' + connection.threadId);
});
//Sign Up Methods
var createUser = function createwithCredentails(post,callback) {
bcrypt.hash(post.password, 10, function(err, hash){
//console.log('Cache Hash : +',hash);
var createUserQuery = connection.query('INSERT INTO users SET ?',{"email":post.email,"password":hash,"username":post.username},function(err,result){
if (err) {
if (err.code == 'ER_DUP_ENTRY') {
//console.log(err.code);
callback(signupErrors.error_5000);
}
else callback(App_errors.error_1003);
}
if (result) {
callback(sucessMsg.success_signup);
}
});
});
}
//connection.query('SELECT * FROM Users Where Username = '' AND Password = ''');
var validateUser = function ValidateUserWithUserNameAndPassword(post,callback) {
var UserCheckQuery = connection.query('SELECT * FROM users WHERE email="'+post.email+'"',function(err, results, fields) {
if (err){
console.log(err);
callback(App_errors.error_1000);
}
if (results.length == 1) {
//console.log(results[0].password,post.password);
var givenPassword = post.password;
var DBhash = results[0].password;
bcrypt.compare(givenPassword, DBhash,function(err, res) {
if (res) {
console.log('Password matched');
var token = Jwt.sign({"email":post.email,"username":post.username},supersecretkey, {
expiresIn: 60*60*5 // expires in 5 hours
});
callback({
message:{
"success":1,
"description":"sucessfully logged in - please cache the token for any queries in future",
"environment":"test",
"errorCode":null
},
"token":token
});
}
if (!res) {
console.log('password doesnt match');
callback(signupErrors.error_6000);
}
if (err) {
console.log('Error Comparing Passwords');
callback(App_errors.error_1004);
}
});
}
else{
callback(signupErrors.error_6000);
}
});
};
var isauthenticate = function isauthenticated(post,route,callback) {
if (post.headers.token) {
Jwt.verify(post.headers.token, supersecretkey, function(err, decoded) {
if (decoded) {
//console.log(decoded);
//From this part the user is Sucessully Authenticated and autherization params can be extracted from token if required
//Write Business Logic in future as per the requirement
//Operation 1 - Update Profile
//Profile Details consists of {1.first name 2.last name 3. profile pictur(base 64 encoded) 4.further settings in future that can be added to DB if required}
if (route == '/update-profile') {
query.updateProfile(connection,decoded.email,post.body,function(response) {
callback(response);
});
}
//callback({"message":"is a valid token"});
}
if (decoded == null) {
console.log('is not a valid token');
//callback(App_errors.error_1000);
}
if (err) {
console.log('error verifying token');
callback(App_errors.error_1000);
}
});
}
else{
callback(App_errors.error_1001);
}
};
module.exports = {
validateUser:validateUser,
createUser:createUser,
isauthenticate:isauthenticate,
connection:connection
}
I am exporting connection object to queryDB.js file. But when I try to log the exported connection object I get undefined object. Why is this happening?
When I pass connection object as function argument, everything works fine. Not sure why?
below is queryDB.js file
var errors = require('./error.js')
var Dbconnection = require('./Database.js').connection;
var updateProfile = function profiledata(connection,email,data,callback) {
console.log(Dbconnection);
if ((!data)|| (Object.keys(data).length < 1)) {
//console.log(data);
callback(errors.error_1001);
}
else{
callback({"message":"update Sucesss"});
//console.log(connection);
//var updateData = mapProfileDataTomodel(data);
//console.log(updateData);
connection.query('SELECT * FROM users WHERE email = "'+email+'"',function(err, result,feilds) {
if (err) throw err;
if (result) {
console.log(result);
}
});
}
}
var mapProfileDataTomodel = function mapProfileDataTomodel(data) {
var profileDataModel = {};
for (var key in data) {
//console.log('looping and mapping data');
if (data.firstname) {
profileDataModel.firstname = data.firstname;
}
if (data.lastname) {
profileDataModel.lastname = data.lastname;
}
if (data.profilepic) {
profileDataModel.profilepic = data.profilepic;
}
}
return profileDataModel;
}
module.exports = {
updateProfile:updateProfile
}
I have commented out connection object log via function arguments.
So, Why I am unable to get the connection object that is exported? But I used the same exported connection object in my app.js file. It did work fine there.

Mongoose, can't update model with for loop

I m doing a javascript function using mongoose to find a group which contains a list of users emails, that part works perfectly. After I want to find each user of the list and add the new group name instead of the old group name, I don't know why, but it doesn't work, the function returns me the group before doing the for loop, and the users are not modified.
Here is my user model :
var userSchema = mongoose.Schema({
local : {
email : String,
password : String,
}
groups : { type: [String], default: []}
});
And here my Group model :
var groupSchema = mongoose.Schema({
title : String,
creator : String,
listOfUsers : { type: [String], default: []}
});
And here my function :
Group.findOne({ '_id': groupId}, function (error, group){
var oldTitle = group.title;
group.title = req.body.title;
group.save();
if(error){
throw (error)
}
for(var i = 0; i < group.listOfUsers.length;i++){
User.findOne({'local.email': group.listOfUsers[i]}, function(error,user){
if(error){
throw (error)
}
for(var j=0;j<user.groups.length;j++){
if(user.groups[j] == oldTitle){
user.groups[j] = group.title;
user.save();
}
}
});
}
return res.json(group);
you can use async to fix the callback problem
async.waterfall(
[
function (callback) {
Group.findOne({
'_id': groupId
}, function (error, group) {
if (error) {
throw (error)
} else {
callback(null, group);
}
})
},
function (group, callback) {
for (var i = 0; i < group.listOfUsers.length; i++) {
User.findOne({
'local.email': group.listOfUsers[i]
}, function (error, user) {
if (error) {
throw (error)
} else {
callback(null, user, group);
}
});
}
},
function (user, group, callback) {
var oldTitle = group.title;
group.title = req.body.title;
for (var j = 0; j < user.groups.length; j++) {
if (user.groups[j] == oldTitle) {
user.groups[j] = group.title;
user.save();
}
}
callback(null, 'done');
}
],
function (err, result) {
console.info("4");
console.info(err);
console.info(result);
});
forgive me if i made any mistake, it is always hard to write code without data, i hope you will understand how i wanted to solve.
and don't forget
var async = require('async');
at the beginning
You should do user.save() only after for loop is finished. I updated for loops with forEach which I feel more comfortable to use.
Group.findbyId(groupId, function(err, group) {
var oldTitle = group.title;
group.title = req.body.title;
if (group.save()) {
listOfUsers.forEach(function(groupUser) {
User.findOne({'local.email' : groupUser}, function (err, user) {
if(user) {
user.group.forEach(function(userGroup) {
if (userGroup == oldTitle) {
userGroup = group.title;
}
})
user.save();
}
});
});
res.json(group);
} else {
res.status(400).json({messsage: 'Error while saving group!'});
}
});

cant add more than one object into db using mongoose

I have a function that is supposed to add new item each time there is a match as below:
function getTimeEntriesFromWorksnap(error, response, body) {
//console.log(response.statusCode);
var counter = 1;
if (!error && response.statusCode == 200) {
parser.parseString(body, function (err, results) {
var json_string = JSON.stringify(results.time_entries);
var timeEntries = JSON.parse(json_string);
_.forEach(timeEntries, function (timeEntry) {
_.forEach(timeEntry, function (item) {
Student.findOne({'worksnap.user.user_id': item.user_id[0]})
.populate('user')
.exec(function (err, student) {
if (err) {
throw err;
}
var newTimeEntry = _pushToObject(student.worksnap.timeEntries, item);
student.worksnap.timeEntries = {};
student.worksnap.timeEntries = newTimeEntry;
student.save(function (err) {
if (err) {
//return res.status(400).send({
// message: errorHandler.getErrorMessage(err)
//});
} else {
//res.json(item);
}
});
});
});
});
});
}
}
For some reason it is only inserting once for each student that it finds.
And my Student schema looks like this:
var StudentSchema = new Schema({
firstName: {
type: String,
trim: true,
default: ''
//validate: [validateLocalStrategyProperty, 'Please fill in your first name']
},
lastName: {
type: String,
trim: true,
default: ''
//validate: [validateLocalStrategyProperty, 'Please fill in your last name']
},
worksnap: {
user: {
type: Object
},
timeEntries: {
type: Object
},
}
});
Any solution?
My Guess is its always pushing the last one... closures...
function getTimeEntriesFromWorksnap(error, response, body) {
//console.log(response.statusCode);
var counter = 1;
if (!error && response.statusCode == 200) {
parser.parseString(body, function (err, results) {
var json_string = JSON.stringify(results.time_entries);
var timeEntries = JSON.parse(json_string);
_.forEach(timeEntries, function (timeEntry) {
_.forEach(timeEntry, function (item) {
saveStudent(item);
});
});
});
}
}
Below is saveStudent function
function saveStudent(item) {
Student.findOne({
'worksnap.user.user_id': item.user_id[0]
})
.populate('user')
.exec(function(err, student) {
if (err) {
throw err;
}
var newTimeEntry = _pushToObject(student.worksnap.timeEntries, item);
student.worksnap.timeEntries = {};
student.worksnap.timeEntries = newTimeEntry;
student.save(function(err) {
if (err) {
//return res.status(400).send({
// message: errorHandler.getErrorMessage(err)
//});
} else {
//res.json(item);
}
});
});
}
OR
wrap it inside a closure...
function getTimeEntriesFromWorksnap(error, response, body) {
//console.log(response.statusCode);
var counter = 1;
if (!error && response.statusCode == 200) {
parser.parseString(body, function(err, results) {
var json_string = JSON.stringify(results.time_entries);
var timeEntries = JSON.parse(json_string);
_.forEach(timeEntries, function(timeEntry) {
_.forEach(timeEntry, function(item) {
(function(item){
Student.findOne({
'worksnap.user.user_id': item.user_id[0]
})
.populate('user')
.exec(function(err, student) {
if (err) {
throw err;
}
var newTimeEntry = _pushToObject(student.worksnap.timeEntries, item);
student.worksnap.timeEntries = {};
student.worksnap.timeEntries = newTimeEntry;
student.save(function(err) {
if (err) {
//return res.status(400).send({
// message: errorHandler.getErrorMessage(err)
//});
} else {
//res.json(item);
}
});
});
}(item))
});
});
});
}
}
Can you use async library and check out...
var async = require('async');
async.map(timeEntries, function (timeEntry, next) {
async.map(timeEntry, function (item, next) {
//your code.
});
});

Unit testing a method that calls other methods

I am new to testing. I am trying to unit-test a method that calls 2 other methods. I tried stubbing those 2 methods, but it looks like the original methods are still getting called. I am trying to test whether my method adds the object the savePoll method returns to the user.polls array.
test.js
var UserStub = sinon.stub();
var PollStub = sinon.stub();
var OptionStub = sinon.stub();
var saveOptionsStub = sinon.stub();
var savePollStub = sinon.stub();
var users = proxyquire('../controllers/users', {
'../models/user': UserStub,
'../models/poll': PollStub,
'../models/option': OptionStub
});
beforeEach(function() {
res = {
json: sinon.spy(),
send: sinon.spy(),
status: function(responseStatus) {
return this;
}
};
req = {
params: {
id: 1
}
};
UserStub.save = function(callback) {
callback(null, req.body);
};
});
describe('add a poll', function() {
it('should add the poll', function() {
req.body = {
name: 'Poll1',
options: [{
text: 'option1',
votes: 0
}, {
text: 'option2',
votes: 1
}]
};
var user = {};
user.polls = [];
UserStub.findById = function(query, callback) {
callback(null, user);
};
sinon.stub(require('../controllers/users'), 'saveOptions').returns([OptionStub, OptionStub]);
sinon.stub(require('../controllers/users'), 'savePoll').returns({});
users.addPoll(req, res);
expect(user.polls).to.equal('[{}]');
});
});
users.js
addPoll: function(req, res) {
var self = this;
User.findById(req.params.user_id, function(err, user) {
if (err) return res.status(400).json(err);
self.saveOptions(req.body.options)
.then(function(optionsArr) {
var pollName = req.body.name;
self.savePoll(pollName, optionsArr)
.then(function(poll) {
user.polls.push(poll);
user.save(function(err, user) {
if (err) return res.status(500).json(err);
res.json(poll);
});
}, function(err) {
return res.status(500).json(err);
});
}, function(err) {
return res.status(400).json(err);
});
});
},
savePoll: function(pollName, optionsArr) {
return new Promise(function(resolve, reject) {
var poll = new Poll();
poll.name = pollName;
poll.options = optionsArr.slice();
poll.save(function(err, poll) {
if (err) {
reject(err);
} else {
resolve(poll);
}
});
});
},
saveOptions: function(options) {
var optsArr = [];
var promises = options.map(function(opt) {
return new Promise(function(resolve, reject) {
var option = new Option(opt);
return option.save(function(err, option) {
if (err) {
reject(Error(err));
} else {
resolve(optsArr.push(option));
}
});
});
});
return Promise.all(promises).then(function() {
return optsArr;
}).catch(function(err) {
console.log(err);
});
}

Categories

Resources