I am Working in a MERN application. In one of my model of express.js I have student schema like below which have unique fields
Fullname: {
type: String,
required: true,
trim: true,
},
AdmissionNumber: {
type: String,
required: true,
trim: true,
maxlength: 10,
unique: true,
},
RollNumber: {
type: Number,
required: true,
trim: true,
maxlength: 4,
},
Age: {
type: Number,
required: true,
maxlength: 2,
},
Email: {
type: String,
trim: true,
required: true,
unique: true,
},
Faculty: {
type: ObjectId,
ref: "Faculty",
required: true,
},
pass: {
type: Number,
default: 0,
}
I am saving the student with the help of form like this
exports.addStudent = (req, res) => {
let form = new formidable.IncomingForm();
form.keepExtensions = true;
form.parse(req, (err, fields) => {
if (err) {
res.status(400).json({
error: "problem with feilds",
});
}
// destructuring feilds
const {
Fullname,
AdmissionNumber,
RollNumber,
Age,
Email,
Faculty,
} = fields;
if (
!Fullname ||
!AdmissionNumber ||
!RollNumber ||
!Age ||
!Email ||
!Faculty
) {
return res.status(400).json({
error: "Please fill all fields",
});
}
// TODO: restriction on fields
let student = new Student(fields);
student.save((err, student) => {
if (err) {
res.status(400).json({
error: "Saving Student in DB failed",
});
console.log(err);
}
res.json(student);
// console.log(student.gender);
});
});
};
When I try to add student it will be added only first time after that it showing an error
I have checked my DB collection there is only one field in the database.
I had this problem before and the solution that worked for me is to delete the collection from the database then try again
Related
I am try to upload images on server and save image path in mongoDB database. but image path not stored in database your text
const UserSchema = new mongoose.Schema({
name: {type: String, required: true, trim: true },
email: {type:String, unique:true, required: true, trim: true, lowercase: true,
validate(value){
if(!validator.isEmail(value)){
throw new Error('Email is Invalid!')
}
}
},
password: {type: String, required:true, trim: true,minlength:7,
validate(value){
if(value.toLowerCase().includes('password')){
throw new Error('Password cannot conatin "password"')
}
}
},
age: {type: Number, required: true, default: 0,
validate(value) {
if(value \< 0) {
throw new Error('Age Must be a Postive number')
}
}
},
tokens: \[{
token: {
type: String,
required: true
}
}\],
avatar:{type: String}
}, {
timestamps: true
})
app.post('/users/me/avatar', authCheck, upload.array('avatar\[\]', 10), async (req,res,next)=\>{
console.log(req.file)
// const buffer = await shrap(req.file.path).resize({width:250,height:250}).png().toFile(req.file.destination, 'resized');
req.user.avatar = req.files.path,
await req.user.save()
res.status(200).send()
}, (error, req,res,next) =\>{
res.status(400).send({
error: error.message
})
})
I am try to upload images on server and save image path in mongoDb database. but image path not stored in database
I am trying to build a forum and have come across some problems when trying to add answers with information of the user to a specific post. I am able to list the answers for a single post in the frontend, however I am unable to populate the user information, as for now I only get an id. Here are my models and endpoints to post and get the answers. What am I missing?
const User = mongoose.model('User', {
username: {
type: String,
required: [true, 'Username is required!'],
unique: true,
lowercase: true,
trim: true
},
email: {
type: String,
required: [true, 'Email is required!'],
unique: true,
lowercase: true,
trim: true,
validate: {
validator: (value) => {
return /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(value)
},
message: "Please enter a valid email address"
}
},
password: {
type: String,
required: [true, 'Password is required!'],
minlength: [8, 'Password must be a minimum of 8 characters!']
},
accessToken: {
type: String,
default: () => crypto.randomBytes(128).toString('hex')
}
})
const Post = mongoose.model('Post', {
title: {
type: String,
required: [true, 'Field cannot be blank'],
minlength: [2, 'Your post must be a minimum of 2 characters!'],
maxlength: [50, 'Your post must be a maximum of 50 characters!']
},
post: {
type: String,
required: [true, 'Field cannot be blank'],
minlength: [2, 'Your post must be a minimum of 2 characters!'],
},
votes: {
type: Number,
default: 0
},
createdAt: {
type: Date,
default: Date.now()
},
answers: [{
type: mongoose.Schema.Types.ObjectId,
ref:'Answer'
}],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
})
const Answer = mongoose.model('Answer', {
answers: {
type: String,
},
number: {
type: Number,
default: 0
},
post: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
createdAt: {
type: Date,
default: Date.now()
}
})
app.get('/posts/:id/answers', authenticateUser, async (req, res) => {
const { id } = req.params
const newAnswer = await Post.findById(id).populate('user', 'username').populate('answers').exec()
res.json({ success: true, newAnswer })
})
app.post('/posts/:id/answers', authenticateUser, async (req, res) => {
const { id } = req.params
const { _id } = req.user
const { answers, post } = req.body
try {
const user = await User.findById(_id)
// get answer and save post id
const newAnswer = new Answer({
answers: req.body.answers,
post: id,
user
})
// save answer
const result = await newAnswer.save()
// find post and push the comment into the array in the same moment
const answeredPost = await Post.findByIdAndUpdate(id, {
$push: {
answers: result
}
}).populate('user', 'username').populate('answers').exec()
res.json({ success: true, answeredPost})
} catch (error) {
res.status(400).json({ success: false, message: 'Invalid request', error })
}
})
Try this:
Post.findById(id).populate('user', 'username').populate({ path : 'answers', populate : { path : 'user'}}).exec()
I have a getter on the price property of my schema.
For some reason, my getter function is not working when I try to query a document from my MongoDB database. The price value comes back exactly as I have it saved in my database, as opposed to a rounded number via Math.floor(v). Fyi, my setter works fine in the same scenario. Any help would be much appreciated!
const schema = mongoose.Schema({
name: { type: String, required: true, lowercase: true },
isPublished: Boolean,
author: {
type: String,
required: function (v) {
return this.isPublished;
},
uppercase:true,
},
price: {
type: Number,
required: true,
get: function (v) {
return Math.floor(v);
},
},
});
const Documents = mongoose.model("Documents", schema);
async function myQuery(id) {
const result = await Documents.findById(id);
if (!result) return debug("Not found...");
debug(result);
}
myQuery("60348d30e7b9bf3878170955");
const schema = mongoose.Schema({
name: { type: String, required: true, lowercase: true },
isPublished: Boolean,
author: {
type: String,
required: function (v) {
return this.isPublished;
},
uppercase: true,
},
price: {
type: Number,
required: true,
get: function (v) {
return Math.floor(v);
},
},
} {
toObject: { getters: true, setters: true },
toJSON: { getters: true, setters: true },
runSettersOnQuery: true
});
Add the following configuration to your schema and give it a try.
I'm currently working on a Library Management System and I'm using MongoDB as my Database so in there I have 4 schemas
User 2) Book 3) Review 4) bookIssue (which handles all the book
issuing)
I'll mention just my User and Book Issue schemas here coz I only want help regarding these two Schemas,
bookIssueHistory: { type: Array, default: null, }
Whenever a book is issued via "bookIssue" Schema I want to store that book's "id" in to the "bookIssueHistory" array (mentioned above) which is in my "userSchema", so I've mentioned both of my schemas below:
const userSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'Please enter your name'],
},
email: {
type: String,
required: [true, 'Please enter your email'],
unique: true,
lowercase: true,
validate: [validator.isEmail, 'Please enter a valid email'],
},
photo: String,
role: {
type: String,
enum: ['user', 'admin'],
default: 'user',
},
password: {
type: String,
required: [true, 'Please enter your password'],
minlength: 8,
select: false,
},
passwordConfirm: {
type: String,
required: [true, 'Re-Enter your password'],
validate: {
validator: function (el) {
return el === this.password;
},
message: 'Entered password and confirmed password do not match',
},
},
passwordChangedAt: Date,
passwordResetToken: String,
passwordResetExpires: Date,
noOfBooksIssued: {
type: Number,
default: 0,
},
currentlyIssuedBooks: {
type: Number,
max: [3, 'You are only allowed to issue 3 books at a time'],
default: 0,
},
bookIssueHistory: {
type: Array,
default: null,
},
active: {
type: Boolean,
default: true,
select: false,
},
});
my book issue schema looks like this:
const bookIssueSchema = mongoose.Schema({
issuedAt: {
type: Date,
default: Date.now,
},
totalIssues: {
type: Number,
default: 0,
},
book: {
type: mongoose.Schema.ObjectId,
ref: 'Book',
required: [true, 'issue must belong to a book.'],
},
user: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: [true, 'issue must belong to a user.'],
},
});
You can use mongoose middleware, in particular the pre-save hook to run some logic before bookIssue get inserted into the database.
bookIssueSchema.pre('save', function () {
// you can access the current document to be saved by `this`
if (this.isNew) { // apply to new bookIssue only
await this.model('User').findByIdAndUpdate(this.user, {
$addToSet: { bookIssueHistory: this.book } // use $addToSet to ensure distinct values, otherwise use $push
})
}
})
Important: The pre-save hook will be run only when you use BookIssue.create() or bookIssue.save() and not when you run BookIssue.insertMany()
Hi I want to tell the user which one is already taken if is Username or Email but the way Im validating this is in the save function if this finds a duplicate it will give you a error 11000 but I cant specify which one is already taken. I want the error to give an index or something I can put in a if statement explaining which one is the duplicate key so I can be more specific with the error. Is there a way i can accomplish this? Also why Im getting always index: 0? Shouldn't be different for each field? Let me know if you have any questions.
Schema
var user = db.Schema({
name: { type: String, required: true},
username: { type: String, required: true, index: { unique: true }},
email: { type: String, required: true, index: { unique: true }},
password: { type: String, required: true, select: false},
admin: { type: Boolean, required: true},
verify: { type: Boolean, required: true},
created_at: { type: String, required: true, default: Date.now },
updated_at: { type: String, required: true, default: Date.now },
campaigns_donated: []
})
Post Action
router.post('/register', function(req, res){
var user = new User()
user.name = req.body.name
user.username = req.body.username
user.email = req.body.email
user.password = req.body.password
user.admin = false,
user.verify = false
user.save(function(err) {
if (err) {
console.log(err);
if (err.code == 11000) {
return res.json({ success: false, message: 'username or email already taken'})
} else {
return res.send(err);
}
}
res.json({ success: true, message: 'User created'})
})
})
Pre Save Function
user.pre('save', function(next) {
var user = this
// hash the password only if the password has been changed or user is new
if (!user.isModified('password')) { return next() }
//Generate Hash function
bcrypt.hash(user.password, 10, function(err, hash) {
if (err) return next(err)
//Change Password to hash
user.password = hash
next()
})
})
Console log error
{ [MongoError: E11000 duplicate key error index: ReachPeeps.users.$username_1 dup key: { : "xandor" }]
name: 'MongoError',
message: 'E11000 duplicate key error index: ReachPeeps.users.$username_1 dup key: { : "xandor" }',
index: 0,
code: 11000,
errmsg: 'E11000 duplicate key error index: ReachPeeps.users.$username_1 dup key: { : "xandor" }' }