Hi I have the following JSON named departments. When i do console.log(departments) i get this.
{ _id: 58089a9c86337d1894ae1834,
departmentName: 'Software Engineering',
clientId: '57ff553e94542e1c2fd41d26',
hodName: 'Mr Shekar Krishna',
noOfEmployees: 90,
hodId: 'djekjakejkjkjekajk3j33',
__v: 0 }
But when i try to assign a value like hodId to a variable like this.
var hodId=departments.hodId;
and then do console.log i get undefined.
Also i need to add this value "hodId" to t to another JSON "user" which is currently like this:
{ fullName: 'Rohit',
password: '123',
contactNum: '00000',
homeNum: '9998889999',
officeNum: '9998889999',
emailId: 'dv000d0v#yopmail.com',
employeeAddress: '10 ,Lakshmi Apartments, Sarai Kale Khan,New Delhi',
clientId: 'general',
clientName: 'Restaurant',
accessLevelId: 'sscaskoo31',
accessLevelName: 'basic',
departmentName: 'test',
departmentId: '58089a9c86337d1894ae1834',
employeeId: 'EMP1102',
employeeGrade: 'A',
employeeGradeId: '1221' }
Suggest what i am doing wrong?
Adding the code
var user=req.body;
// var hodId="";
if (req.body.clientId=="general") {
user.accessLevelName="basic";
}
if (!(req.body.departmentId==null || req.body.departmentId=="")) {
Departments.find({ '_id': req.body.departmentId },function(err, departments) {
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err) {
res.send(err);
}
console.log("department"+departments);
// user.hodId="test";
user.departmentName=departments.departmentName;
var newUser =new User(user);
newUser.save(function(err,obj) {
if (err) {
return res.json({success: false, msg: "User Name Already Exists"});
} else {
var token = jwt.encode(obj, config.secret);
res.json({success: true, token: 'JWT ' + token,msg: 'Successful created new user.',user:obj});
}
});
});
} else{
newUser.save(function(err,obj) {
if (err) {
return res.json({success: false, msg: "User Name Already Exists"});
} else {
var token = jwt.encode(obj, config.secret);
res.json({success: true, token: 'JWT ' + token,msg: 'Successful created new user.',user:obj});
}
The mongoose .find() method returns an Array, not an object.
The output of console.log(departmants) is, or at least should be:
[{ _id: 58089a9c86337d1894ae1834,
departmentName: 'Software Engineering',
clientId: '57ff553e94542e1c2fd41d26',
hodName: 'Mr Shekar Krishna',
noOfEmployees: 90,
hodId: 'djekjakejkjkjekajk3j33',
__v: 0 }]
Which means that to access what youre looking for you need to access the first object in the array first.
var hodId=departments[0].hodId;
Once you have that var you can then add it to another user
user.hodId = hodId;
Related
Basically I have create a mongo database and have made a Post model which referenced to the User by _id.
I want to get the information on the post user have so I made a callback function in exec() when I am populating the selected User. But the result is an empty array.
I except populate.exec() helps me to get more info on post like this
{
posts: [ {
_id: 5f287dd39eb82544302b974b,
title: 'It;s a good day pt.3',
content: 'Sunny on the morning and little cloudy in the evening :)',
__v: 0
}
],
_id: 5f287adf86b8a617300122a7,
email: 'bob#gmail.com',
name: 'Bob',
__v: 2
}
However, the result is just
{
posts: [],
_id: 5f287adf86b8a617300122a7,
email: 'bob#gmail.com',
name: 'Bob',
__v: 2
}
I am appreciate if someone who can help me with this. My js code shows below!
let mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/blog_demo_2", {useNewUrlParser: true, useUnifiedTopology: true});
let postSchema = new mongoose.Schema({
title: String,
content: String
});
let Post = mongoose.model("Post", postSchema);
let userSchema = new mongoose.Schema({
email: String,
name: String,
posts: [{
type: mongoose.Schema.Types.ObjectId,
rel: 'Post'
}]
});
let User = mongoose.model("User", userSchema);
User.create({
email: "bob#gmail.com",
name: "Bob"
});
Post.create({
title: "It's a good day pt.3",
content: "Sunny on the morning and little cloudy in the evening :)"
}, function (err, newlyPost) {
if(err){
console.log(err);
}else{
User.findOne({email: "bob#gmail.com"}, function (err, foundUser) {
if(err){
console.log(err);
}else{
foundUser.posts.push(newlyPost);
foundUser.save();
}
})
}
});
User.findOne({email: "bob#gmail.com"}).populate("posts").exec(function (err, user) {
if(err){
console.log(err);
}else{
console.log(user);
}
});
You have
posts: [{
type: mongoose.Schema.Types.ObjectId,
rel: 'Post'
}]
It should be ref as in reference, not rel
posts: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}]
On calling .map on an array of objects, it's throwing an error of TypeError: friends.map is not a function.
when I do it in vanilla js with the object, it works fine, but that's after I enclose the id and _id values in quotes.
is that the cause as it's of type ObjectId in Mongoose? if so, how do I fix it?
var UserSchema = new Schema({
username : String,
firstName : String,
lastName : String
friends : [{ id: { type: Schema.Types.ObjectId, ref: 'User'}, status: Number }]
});
app.get('/getFriends', requireLogin, function(req, res) {
User.findOne({ _id: req.user.id }, 'friends')
.populate({
path: 'friends.id',
model: 'User',
select: 'username firstName lastName -_id'
})
.exec(function(err, friends) {
console.log(typeof(friends))
console.log(friends)
friends = friends.map(function(v) {
delete(v._id);
delete(v.status);
return v;
});
res.json(friends);
})
})
events.js:163
throw er; // Unhandled 'error' event
^
TypeError: friends.map is not a function
the output of console.log(friends)
[ { _id: 590bbb88858367c9bb07776e,
status: 2,
id: 590bba9c858367c9bb077759 },
{ _id: 590bbb95858367c9bb07776f,
status: 2,
id: 590bbad5858367c9bb07775f },
{ _id: 590bbb9e858367c9bb077770,
status: 2,
id: 590bbb05858367c9bb077765 },
{ _id: 590bbbaa858367c9bb077771,
status: 2,
id: 590bbaf2858367c9bb077763 },
{ _id: 590bbbb6858367c9bb077772,
status: 2,
id: 590bbae5858367c9bb077761 },
{ _id: 590bbbc5858367c9bb077773,
status: 2,
id: 590bbabe858367c9bb07775d },
{ _id: 590bbbef858367c9bb077774,
status: 2,
id: 590bbab2858367c9bb07775b } ]
In your code, you are calling .findOne on the User model to query for a document with the _id in the params.
.findOne returns a single mongoose document (Not an array), so the second argument in the callback for exec should refer to the user with with that _id, with only a populated friends property. I don't quite see how you would be getting the logged output you provided. Try something along these lines:
app.get('/getFriends', requireLogin, function(req, res) {
User.findOne({ _id: req.user.id }, 'friends')
.populate({
path: 'friends.id',
model: 'User',
select: 'username firstName lastName -_id'
})
.exec(function(err, user) {
var friends = user.friends.map(function(v) {
delete(v._id);
delete(v.status);
return v;
});
res.json(friends);
})
})
In users.js:
var mongoose = require('mongoose');
var User = mongoose.model('user', {
username: {
type: String,
required: true,
unique: true,
lowercase: true,
},
tasks: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Tasks',
}],
});
module.exports = User;
I then add a newUser named user1 and save to mongo.
The mongo doc looks like:
{
"_id" : ObjectId("574fb94f6a1e7d1826c16058"),
"username" : "user1",
"tasks" : [ ],
"__v" : 0
}
then try to fetch the document and it works fine in this handler:
In handlerA.js:
var User = require('../models/users.js');
module.exports.getUser = function(req, res){
User.findOne({username: "user1"}, function(err, data){
if(err){
console.log('getUser err', err);
res.send('ERROR')
} else {
console.log('getUser fx success = ', err, data);
res.send(data)
}
});
};
The result of the console.log:
getUser fx success = null { tasks: [], __v: 0, username: 'user1', _id: 574fb94f6a1e7d1826c16058 }
but same code fails in this other handler in a separate file.
In handlerB.js:
var User = require('../models/users.js');
module.exports.addStuff = function(req, res){
User.findOne({username: "user1"}, function(err, data){
if(err){
console.log('addStuff err', err);
res.send('ERROR')
} else {
console.log('addStuff fx success =', err, data);
res.send(data)
}
});
};
The result of the console.log:
addStuff fx success null null
Tried....and Failed....
I also tried this other solution from this question: Mongoose query return null
Mongoose pluralizes model names so it's running find on the "blogposts" collection instead of "blogpost". That said, your query in the mongo shell is on the "blogmodel" collection. In that case:
var BlogModel = mongoose.Model("BlogModel", ..)
or pass the collection name as the third param:
var BlogModel = mongoose.model("BlogPost", schema, "blogmodel")
This solution results in handlerA.js returning a null document as well as handlerB.js.
Thanks for your time. Much appreciated.
ADDENDUM.
I ran a find({}) under both the User and the Tasks models in handlerB.js
The returned document IN BOTH cases is based on the Tasks model.
see console.logs below for User.find({}) and Tasks.find({})
the err is the null value then the data.
How badly have I broken things? How can a Model.find return data that is not even in the model?
User.find({},funtion(err, data) ____________________
console.log of err then data
null
[ { subtasks: [],
team: [ [Object] ],
__v: 0,
maintask: '1',
_id: 574fce63d744cba421f750c1
},
{ subtasks: [],
team: [ [Object] ],
__v: 0,
maintask: '2',
_id: 574fce65d744cba421f750c2
}
]
Tasks.find({},function(err, data) ___________________
console.log of err then data
null
[ { subtasks: [],
team: [ [Object] ],
__v: 0,
maintask: '1',
_id: 574fce63d744cba421f750c1 },
{ subtasks: [],
team: [ [Object] ],
__v: 0,
maintask: '2',
_id: 574fce65d744cba421f750c2
},
]
This is the Tasks model...
tasks.js
var mongoose = require('mongoose');
var subtaskSchema = new mongoose.Schema({
subtask: {
type: String,
},
team: {
type: Array,
'defualt': [],
},
done: {
type: Boolean,
'defualt': false,
},
});
var Tasks = mongoose.model('tasks', {
maintask: {
type: String,
},
subtasks: {
type: [subtaskSchema],
},
team: {
type: Array,
'defualt': [],
},
done: {
type: Boolean,
'defualt': false,
},
});
module.exports = Tasks;
The mongoose docs suggest to define a model like so, did you try this?
var schema = new mongoose.Schema({ name: 'string', size: 'string' });
var Tank = mongoose.model('Tank', schema);
For some reason, whenever I create a new user in the database, it tries to add another user before and then errors out.
I am using Yeoman's generator angular-fullstack to create an api for my application. In this last week, I started noticing that when my database was populating, it did not display "finished populating users", signifying that it is not successfully adding users in my seed.js file. Here is my seed.js file.
Seed.js
'use strict';
var Thing = require('../api/thing/thing.model');
var User = require('../api/user/user.model');
var Item = require('../api/item/item.model');
var Calendar = require('../api/calendar/calendar.model');
Thing.find({}).remove(function() {});
User.find({}).remove(function() {
User.create({
provider: 'local',
role: 'student',
name: 'Student',
email: 'student#test.com',
password: 'test',
pin: '0807'
}, {
provider: 'local',
role: 'teacher',
name: 'Teacher',
email: 'teacher#test.com',
password: 'test',
pin: '0807'
}, {
provider: 'local',
role: 'admin',
name: 'Admin',
email: 'admin#admin.com',
password: 'admin',
pin: '0807'
}, function() {
console.log('finished populating users');
}, function(err) {
console.log(err);
});
});
Calendar.find({}).remove(function() {});
console.log("Removed Calendars");
Item.find({}).remove(function () {
Item.create({
calendarId: "dd7sfasd8f8sd",
title: "title",
description: "description",
date: new Date(),
checklists: [],
attachments: [],
status: "Not Completed",
edit: false,
verification: "test", //This will not be here in the long run
verify: false
}, {
calendarId: "323k3k2l23lk4j4",
title: "other",
description: "description",
date: new Date(),
checklists: [],
attachments: [],
status: "Completed",
edit: false,
verification: "test", //This will not be here in the long run
verify: false
}, {
calendarId: "323k3k2l23lk4j4",
title: "title",
description: "description",
date: new Date(),
checklists: [],
attachments: [],
status: "Verified",
edit: false,
verification: "test", //This will not be here in the long run
verify: false
}, {
calendarId: "323k3k2l23lk4j4",
title: "test",
description: "description",
date: new Date(),
checklists: [],
attachments: [],
status: "Not Completed",
edit: false,
verification: "test", //This will not be here in the long run
verify: false
}, function() {
console.log('finished populating items');
}
);
});
When I added the function when an error occurred, it displayed this:
Express server listening on 9000, in development mode
Done waiting!
Running "open:server" (open) task
Running "watch" task
Waiting...
{ _id: 5704a4d8b414a48822cd30a6, students: [], role: 'teacher' }
[Error: Invalid or no password]
finished populating items
As you might notice, the object displaying as the user to add is not the users in my seed.js file. To save time in looking through my entire model, here is the method where I am printing that user being created and where this error is occuring:
UserSchema
.pre('save', function(next) {
if (!this.isNew) return next();
console.log(this);
if (!validatePresenceOf(this.hashedPassword) && authTypes.indexOf(this.provider) === -1) {
next(new Error('Invalid or no password'));
if (!validatePresenceOf(this.hashedPin))
next(new Error('Invalid pin'));
} else {
next();
}
});
However, for more information into this error, I have the whole file shown below:
user.model.js
'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var crypto = require('crypto');
var authTypes = ['github', 'twitter', 'facebook', 'google'];
var Student = new Schema({
firstName: String,
lastName: String,
age: Number
});
var UserSchema = new Schema({
name: String,
username: String,
email: { type: String, lowercase: true },
role: {
type: String,
default: 'teacher'
},
teachersEmail: { type: String, lowercase: true },
students: [Student],
status: String,
hashedPassword: String,
hashedPin: String,
hasPassword: Boolean,
provider: String,
salt: String,
pinSalt: String,
facebook: {},
twitter: {},
google: {},
github: {}
});
/**
* Virtuals
*/
UserSchema
.virtual('password')
.set(function(password) {
this._password = password;
this.salt = this.makeSalt();
this.hashedPassword = this.encryptPassword(password);
})
.get(function() {
return this._password;
});
UserSchema
.virtual('pin')
.set(function(pin) {
this._pin = pin;
this.pinSalt = this.makeSalt();
this.hashedPin = this.encryptPin(pin);
})
.get(function() {
return this._pin;
});
// Public profile information
UserSchema
.virtual('profile')
.get(function() {
return {
'name': this.name,
'role': this.role
};
});
// Non-sensitive info we'll be putting in the token
UserSchema
.virtual('token')
.get(function() {
return {
'_id': this._id,
'role': this.role
};
});
/**
* Validations
*/
// Validate empty email
UserSchema
.path('email')
.validate(function(email) {
if (authTypes.indexOf(this.provider) !== -1) return true;
return email.length;
}, 'Email cannot be blank');
// Validate empty password
UserSchema
.path('hashedPassword')
.validate(function(hashedPassword) {
if (authTypes.indexOf(this.provider) !== -1) return true;
return hashedPassword.length;
}, 'Password cannot be blank');
// Validate empty pin
UserSchema
.path('hashedPin')
.validate(function(hashedPin) {
return hashedPin.length;
}, 'PIN cannot be blank');
// Validate empty pin
UserSchema
.path('hashedPin')
.validate(function(hashedPin) {
return hashedPin.length == 4;
}, 'PIN must be 4 characters in length');
// Validate email is not taken
UserSchema
.path('email')
.validate(function(value, respond) {
var self = this;
this.constructor.findOne({email: value}, function(err, user) {
if(err) throw err;
if(user) {
if(self.id === user.id) return respond(true);
return respond(false);
}
respond(true);
});
}, 'The specified email address is already in use.');
var validatePresenceOf = function(value) {
return value && value.length;
};
/**
* Pre-save hook
*/
UserSchema
.pre('save', function(next) {
if (!this.isNew) return next();
console.log(this);
if (!validatePresenceOf(this.hashedPassword) && authTypes.indexOf(this.provider) === -1) {
next(new Error('Invalid or no password'));
if (!validatePresenceOf(this.hashedPin))
next(new Error('Invalid pin'));
} else {
next();
}
});
/**
* Methods
*/
UserSchema.methods = {
/**
* Authenticate - check if the passwords are the same
*
* #param {String} plainText
* #return {Boolean}
* #api public
*/
authenticate: function(plainText) {
if (this.hashedPassword) {
return this.encryptPassword(plainText) === this.hashedPassword;
} else {
return !!(this.google || this.facebook);
}
},
verify: function(plainText) {
return this.encryptPin(plainText) === this.hashedPin;
},
/**
* Make salt
*
* #return {String}
* #api public
*/
makeSalt: function() {
return crypto.randomBytes(16).toString('base64');
},
/**
* Encrypt password
*
* #param {String} password
* #return {String}
* #api public
*/
encryptPassword: function(password) {
if (!password || !this.salt) return '';
var salt = new Buffer(this.salt, 'base64');
return crypto.pbkdf2Sync(password, salt, 10000, 64).toString('base64');
},
encryptPin: function(pin) {
if (!pin || !this.pinSalt) return '';
var pinSalt = new Buffer(this.pinSalt, 'base64');
return crypto.pbkdf2Sync(pin, pinSalt, 10000, 64).toString('base64');
}
};
module.exports = mongoose.model('User', UserSchema);
Finally, I decided to separately add users in my seed.js file to see what happens, like so...
User.find({}).remove(function() {
User.create({
provider: 'local',
role: 'student',
name: 'Student',
email: 'student#test.com',
password: 'test',
pin: '0807'
}, function() {
console.log('Added user');
}, function(err) {
console.log(err);
});
User.create({
provider: 'local',
role: 'teacher',
name: 'Teacher',
email: 'teacher#test.com',
password: 'test',
pin: '0807'
}, function() {
console.log('Added user');
}, function(err) {
console.log(err);
});
User.create({
provider: 'local',
role: 'admin',
name: 'Admin',
email: 'admin#admin.com',
password: 'admin',
pin: '0807'
}, function() {
console.log('Added user');
}, function(err) {
console.log(err);
});
});
Here is what the terminal displayed:
Running "watch" task
Completed in 2.258s at Wed Apr 06 2016 00:08:34 GMT-0600 (Mountain Daylight Time) - Waiting...
{ _id: 5704a7e2d85623902a78e1fc, students: [], role: 'teacher' }
[Error: Invalid or no password]
{ _id: 5704a7e2d85623902a78e1fe, students: [], role: 'teacher' }
[Error: Invalid or no password]
{ _id: 5704a7e2d85623902a78e200, students: [], role: 'teacher' }
[Error: Invalid or no password]
finished populating items
The main problem here, is that it is adding a user that I did not add. (I added three. the first one is named "Student". The terminal is showing a user with no name, no email, nothing. Keep in mind that when I add users through my signup screen, this does not happen. The user is added fine...
What could be causing this?
Take a look at the following schema design:
var message = new Schema({
receivers: [User],
message: String,
owner: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
var user = new Schema({
name: String,
photo: String
});
var inbox = new Schema({
messages: [Message],
owner: {
type: Schema.Types.ObjectId,
required: true
},
sequence: Number
});
When I try to create a new message with:
var newMessage = {
receivers: ['<id1>', '<id2>'],
message: 'Hello world',
owner: '<userId>'
}
Inbox.findOneAndUpdate({
owner: '<userId>'
}, {
$push: {
messages: newMessage
},
$set: {
sequence: '<sequence>'
}
}, {
upsert: true
}, callback);
It returns the following error:
MongooseError.CastError "Cast to undefined failed for value [object Object] at path "messages""
What am I doing wrong? How can I make it work?
Thanks.
The receivers field for the message object is expecting an array of objects with the User schema, not an array of ObjectId's hexadecimal string representation. Thus you need to replace the receivers array with the actual objects represented by the ids, something like
var newMessage = {
receivers: ['<id1>', '<id2>'],
message: 'Hello world',
owner: '<userId>'
};
Users.find({ "_id": {"$in": newMessage.receivers} }, function (err, users){
// handle error
if (err) throw err;
// do the update
newMessage.receivers = users;
Inbox.findOneAndUpdate(
{ owner: '<userId>'},
{
$push: { messages: newMessage },
$set: { sequence: '<sequence>' }
},
{ upsert: true}, callback
);
});