How to solve MongoError: E11000 duplicate key error collection - mongodb

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

Multer images array not store in mongoDB Database

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

Problems getting populate to work correctly

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()

Why isn't my Getter function working with Mongoose?

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.

Is there any way in mongoose to access other Schema fields and update those fileds when a "document" is saved into the DB?

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()

Mongo username and email unique fields validation

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" }' }