im getting error: User is not a constructor when trying to add new document to my database. before I used mongoose.model without the Schema method and it worked great but I had to add validator and it needs this syntax and since then I can't make it work
CODE:
var UserSchema = mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, index: true, unique: true, required: true },
password: { type: String, required: true }
});
UserSchema.plugin(uniqueValidator);
let User = mongoose.model("user", UserSchema);
module.exports = User;
router.post('/', (req, res) => {
var user = new User({
username: req.body.username,
email: req.body.email,
password: req.body.password
});
// save the user
user.save(function (err) {
if (err) {
console.log('Error in Saving user: ' + err);
throw err;
}
console.log('User Registration succesful');
// return done(null, userData);
res.status(200).send({user: user})
});
});
mongoose.Schema is a constructor, so you need to call it with "new":
var UserSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, index: true, unique: true, required: true },
password: { type: String, required: true }
});
ok I fixed my issue instead of
module.exports = User;
I had to do:
module.exports = {User};
Related
I am trying to encrypt some passwords and get its salt before saving my model to mongoose in Nestjs, but simply using this to refer to the schema itself doesn't yield any results as it refers to the UserSchemaProvider object itself, instead of the current model I'm trying to save.
My schema provider:
export const UserSchemaProvider = {
name: 'User',
useFactory: (): mongoose.Model<User> => {
const UserSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
birthday: { type: Date, required: true },
celphoneNumber: String,
whatsapp: Boolean,
promo: Object,
status: String
});
UserSchema.pre<User>('save', async (next) => {
const user = this;
console.log(user);
if (user.password) {
const salt = await bcrypt.genSalt();
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) return next(err);
user.password = hash;
next();
});
}
});
return UserSchema;
},
};
and my user Module comes below:
#Module({
imports: [
MongooseModule.forFeatureAsync([
UserSchemaProvider]),
HttpModule
],
controllers: [UsersController],
providers: [UsersService, Validator, ValidationPipe, IsEmailInUseConstraint, GoogleRecaptchaV3Constraint],
})
:Nest Platform Information:
platform-express version: 6.10.14
mongoose version: 6.3.1
common version: 6.10.14
core version: 6.10.14
Your pre hook handler shouldn't be an arrow function () => {}. mongoose handler will need to have the execution context to point to a current document being saved. When using arrow function, your execution context of the pre hook is no longer the document, hence, this inside of the handler isn't the document itself anymore.
export const UserSchemaProvider = {
name: 'User',
useFactory: (): mongoose.Model<User> => {
const UserSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
birthday: { type: Date, required: true },
celphoneNumber: String,
whatsapp: Boolean,
promo: Object,
status: String
});
UserSchema.pre<User>('save', async function(next) { // <-- change to a function instead
const user = this;
console.log(user);
if (user.password) {
const salt = await bcrypt.genSalt();
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) return next(err);
user.password = hash;
next();
});
}
});
return UserSchema;
},
};
What am I missing here? I want to add a sub document to the User schema I already have the schema predefined else where.
User.findById(req.body.id, function(err, user) {
if (err) return console.log(err);
reivews: [{
reviewer: req.body.name,
content: req.body.content
}]
user.save(function(err) {
if (err) console.log(err);
res.send('saved')
})
})
It's saying its saved but I don't see the review in the for the user with the id I tried to save to.
Schema
const Review = new Schema({
reviewer: String,
date : { type: Date, default: Date.now },
content : String,
isLive : { type: Boolean, default: false }
});
const User = new Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
createdAt: { type: Date, default: Date.now },
reviews: [Review]
});
User.plugin(passportLocalMongoose);
module.exports = mongoose.model('Review', Review);
module.exports = mongoose.model('User', User);
Please try this
User.findById(req.body.id, function(err, user) {
if (err) return console.log(err);
if (user.reviews === undefined || user.reviews.length == 0) {
user.reviews = [];
}
user.reviews.push({
reviewer: req.body.name,
content: req.body.content
});
user.save(function(err) {
if (err) console.log(err);
res.send('saved')
})
})
And ensure that data in user as per the defined Schema
I am currently running MongoDB shell version 3.4.7 and I keep getting this error of createUser not being a function where User is an object created like so from a different folder
const UserSchema = mongoose.Schema({
name: {type: String},
email: {type:String, required: true},
username:{type: String, required: true},
password:{type: String, required: true}
});
const User = module.exports = mongoose.model('User', UserSchema);
and used like so.
router.post('/register', (req, res, next) =>{
let newUser = new User({
name: req.body.name,
email: req.body.email,
username: req.body.username,
password: req.body.password
});
User.createUser(newUser, (err, user) =>{
if(err){
res.json({success: false, msg: "Failed to register user"});
} else{
res.json({success: true, msg: "User registered"});
}
});
});
In your second file where you are using User instance you should include
following line before proceeding
var User = require('../models/user');
I want the post's creator to be a user Schema. So i have 2 Schema
post.js
const mongoose=require('mongoose');
mongoose.Promise = global.Promise;
const Schema= mongoose.Schema;
const postSchema= new Schema({
body:{ type: String, required:true, validate:bodyValidators},
createdBy: { type: Schema.Types.ObjectId,ref:'User'}, // this one
to: {type:String, default:null },
createdAt: { type:Date, default:Date.now()},
likes: { type:Number,default:0},
likedBy: { type:Array},
dislikes: { type:Number, default:0},
dislikedBy: { type:Array},
comments: [
{
comment: { type: String, validate: commentValidators},
commentator: { type: String}
}
]
});
module.exports = mongoose.model('Post',postSchema);
user.js
const mongoose=require('mongoose');
mongoose.Promise = global.Promise;
const Schema= mongoose.Schema;
const userSchema=new Schema({
email: { type: String, required: true, unique: true, lowercase: true, validate: emailValidators},
username: { type: String, required: true, unique: true, lowercase: true, validate: usernameValidators},
password: { type: String, required: true,validate: passwordValidators},
bio: { type:String,default:null},
location: {type:String, default:null},
gender: {type:String,default:null},
birthday: { type:Date,default:null},
img: { type:String, default:'Bloggy/uploads/profile/avatar.jpeg'}
});
module.exports = mongoose.model('User',userSchema);
When a user creates a new post, I save his _id into a new post object
const post= new Post({
body: req.body.body,
createdBy:user._id,
createdAt:Date.now()
});
And when i want to recover all posts with their assigned author
router.get('/allPosts',(req,res)=>{
Post.find().populate('createdBy').exec((err,posts)=>{
if(err){
res.json({success:false,message:err});
}
else{
if (!posts) {
res.json({success:false,message:"No posts found"});
}
else{
res.json({success:true,posts:posts});
}
}
}).sort({'_id':-1}); // the latest comes first
});
It doesn't work though i've followed the documentation. The error i get is TypeError: Post.find(...).populate(...).exec(...).sort is not a function
What am I doing wrong ? Am I missing something ? Maybe the fact that both models are not in the same file ?
Remove execPopulate() it might work. It worked for me.
.exec() returns a Promise and has no method called .sort().
.sort() goes before .exec() as in Post.find(...).populate(...).sort(...).exec(...)
Look at 3rd example in the documentation.
I want to do something like following code, but it failed.
var User = new Schema({
name: { type: String, required: true },
phone_number: { type: String, required: true },
modified: { type: Date, default: Date.now },
contacts: [{
user: { type : Schema.ObjectId, ref : 'User' }
}]
});
var UserModel = mongoose.model('User', User);
Is it able to achieve that purpose?
I think I used the wrong way to check it, actually it works.
Following is my test :
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.connect('localhost', 'contacts_test');
var User = new Schema({
name: { type: String, required: true },
phone_number: { type: String, required: true },
modified: { type: Date, default: Date.now },
contacts: [
{
user: { type: Schema.ObjectId, ref: 'User' }
}
]
});
var UserModel = mongoose.model('User', User);
mongoose.connection.on('open', function () {
var user1 = new UserModel({name: 'kos', phone_number: "003"});
user1.save(function (err) {
if (err) throw err;
var user2 = new UserModel({name: 'java', phone_number: "008"});
user2.contacts = [{user: user1._id}];
user2.save(function (err) {
UserModel.findById(user2._id)
.populate('contacts.user')
.exec(function (err, user) {
if (err) console.error(err.stack || err);
console.log('user name: ' + user.name);
console.error('contact of first result : ', user.contacts[0].user.name);
mongoose.connection.db.dropDatabase(function () {
mongoose.connection.close();
});
});
});
});
});