Mongoose - caused by :: 11000 E11000 duplicate key error index? - node.js

Why do I get this duplicate error - Error creating new user: WriteError({"code":11000,"index":0,"errmsg":"insertDocument :: caused by :: 11000 E11000 duplicate key error index?
All the provided fields are not empty at all.
Schema:
// Declare schema
var userSchema = new mongoose.Schema({
username: {type: String, required: true, index: {unique: true}},
password: {type: String, required: true},
created_on: {type: Date, default: Date.now}
});
Post:
// Create - POST
// Create the first method of the API : POST used to create a new user.
router.post("/", function(req, res, next) {
// Get values from POST request
var username = req.body.username;
var password = req.body.password;
console.log(req.body); // { username: 'tealou', password: 'test123' }
// Create new user document
User.create({
username: username,
password: password
}, function(err, user) {
console.log(user); // undefined
if (err) {
console.log("Error creating new user: " + err);
res.send("Error creating new user.");
} else {
console.log("POST creating new user: " + username);
res.json(user);
}
})
});
Error:
Error creating new user:
WriteError({"code":11000,"index":0,"errmsg":"insertDocument :: caused
by :: 11000 E11000 duplicate key error index: iotdb.users.$name_1 dup
key: { : null
}","op":{"username":"tealou","password":"$2a$10$7mPGND2FRuJDGnXaVTnkru2.xsGn2Ksf8veBKur4ouD9VUNj60RaC","_id":"5786020088245d33140d6f94","created_on":"2016-07-13T08:55:28.279Z","__v":0}})
any ideas?

You initially had a field called name in your schema, that was set to unique.
How do I know? Because of the error telling me so:
duplicate key error index: **iotdb.users.$name_1**
You renamed the field to username, but didn't remove the old index. By default, MongoDB will set the value of a non-existent field to null in that case.
Relevant documentation here:
If a document does not have a value for the indexed field in a unique index, the index will store a null value for this document. Because of the unique constraint, MongoDB will only permit one document that lacks the indexed field.
To solve this, you need to remove the index for the renamed name field.

Dropping the collection and allowing my code to recreate it, is what worked for me.

Related

MongoDB E11000 duplicate key error collection with no unique field in schema

I'm setting up a simple blog form with title, content, and json base64 image data to pass to a local MongoDB server. This is my post route:
router.post('/:userName/posts/new', isAuthenticated, async (req, res) => {
let parsedImage = req.body.file != null && req.body.file != '' ? JSON.parse(req.body.file).data : ''
const newPost = new Post({
title: req.body.title,
content: req.body.content,
imageJson: parsedImage
})
try {
await newPost.save()
res.redirect("/account")
} catch (e) {
console.log(e)
res.redirect("/home")
}
})
And this is my schema model:
const mongoose = require('mongoose');
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
content: {
type: String,
required: true,
},
imageJson: {
type: String
}
});
module.exports = mongoose.model('Post', postSchema)
no unique: true as you can see. The first time I tried running this, it ran perfectly, redirecting directly to the /account page, as intended in the try catch block. But, on a second attempt, using a different image, different content, and different title, it threw this error:
MongoError: E11000 duplicate key error collection: fullstacksus.posts index: userName_1 dup key: { userName: null }
I have no idea what's going on since userName is a database name used in my user account route, but not in my post-making route. Why is it showing up again? Thanks for your answers.
In your MongoDB there is a unique index on {userName: 1}. Since your schema does not have a userName field, it is missing, i.e. null, in every document, so the index rejects it.
Use the mongo shell to connect and drop the index.

how to save new record even if same record exist with status false in unique schema using mongoose node js

Need to a save new record even if one record already exists with status false in unique schema using mongoose node js. I have one record along with {status:false} by updating status true to false while deleting that record. Now i try to add a new record. but new record is not crated. because i have apply unique: true in mongoose schema. I need to apply unique : true, but same time need to create new record if it's status false for exist one. So can anyone give some suggestion
Mongoose, nodejs with mongoose-beautiful-unique-validator
//schema model
var userSchema = new mongoose.Schema({
userName: {
type: String,
required: true,
unique: true
})
//save user function inside module export function
const user= mongoose.model('userSchema');
user.userName = fields.username;
user.save((err, doc) => {
if (!err){
res.send(true);
} else {
console.log(err);
return;
}
})
Expected result:
[
{_id: 12345, userName: 'Uday', status:false},
{_id: 67894, userName: 'Uday', status:true}
]
Actual result:
I got duplicate error When i try to save name with Uday with status: true
[
{_id: 12345, userName: 'Uday', status:false},
]
If you want duplicate entries for the username then you need to remove unique: true from schema design, because you can't save the same username twice in same collections.
And if your requirement is just to update status so you can use update query instead of save/insert.
Your id is alway unique in mongodb. Without same id you only can insert data but same id its not possible.
Drop the required attribute from your Schema, then you could pass a callback to pre('save', callback) that checks 2 things:
Does the username already exists (just check the return from Model.find({username: usernameToCheck}, callback));
In your callback, check for the status attribute, if its false then throw an exception, else save your document.

Issue in saving registered user to MongoDB in Node JS - Express application

I am new to Node.js and trying to create a chat application program. For that I have created a Signup registration form with express framework. The data will be saved in MongoDB. Application uses passport middleware signup functionality. Issue is when submitting a new user for second time I am not able to see the data in mongoDB, instead i can see only the first data. I set the mongodb debug option to true, after submitting the form, user submitted data will be seen through console.
Please see the github code which i created: https://github.com/Deepesh316/jabarchat
Please see the mongodb user details getting saved data code: passport-local.js
passport.use('local.signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, (req, email, password, done) => {
User.findOne({'email': email}, (err, user) => {
// Network or Internet connection error
if(err) {
return done(err);
}
if(user) {
return done(null, false, req.flash('error', 'User with email already exist'));
}
// Creating new instance of user and save it to database
const newUser = new User();
newUser.username = req.body.username;
newUser.email = req.body.email;
newUser.password = newUser.encryptPassword(req.body.password);
newUser.save((err) => {
done(null, newUser);
});
});
}));
Below is the code snippet for Model:
const mongoose = require('mongoose');
const bcrypt = require('bcrypt-nodejs');
const userSchema = mongoose.Schema({
username: { type: String, unique: true },
fullname: { type: String, unique: true, default: ''},
email: { type: String, unique: true },
password: { type: String, default: ''},
userImage: { type: String, default: 'default.png'},
facebook: { type: String, default: ''},
fbTokens: Array,
google: { type: String, default: ''},
googleTokens: Array
});
userSchema.methods.encryptPassword = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(10), null);
};
userSchema.methods.validUserPassword = function(password) {
return bcrypt.compareSync(password, this.password);
};
module.exports = mongoose.model('User', userSchema);
The error message is saying that there's already a record with null as the fullname. In other words, you already have a user without an fullname.
The relevant documentation for this:
If a document does not have a value for the indexed field in a unique index, the index will store a null value for this document. Because of the unique constraint, MongoDB will only permit one document that lacks the indexed field. If there is more than one document without a value for the indexed field or is missing the indexed field, the index build will fail with a duplicate key error.
You can combine the unique constraint with the sparse index to filter these null values from the unique index and avoid the error.
Sparse indexes only contain entries for documents that have the indexed field, even if the index field contains a null value.
In other words, a sparse index is ok with multiple documents all having null values.
Check with mydb.users.getIndexes() if this is the case and manually remove the unwanted index with mydb.users.dropIndex()

How to get around E11000 MongoError without deleting 'unique: true'

I am trying to build a forum in order to learn the MEAN stack. I ran into an issue while using mongoose...
I have this...
var UserSchema = new Schema({
id: ObjectId,
firstName: String,
lastName: String,
role: String,
email: {
type: String,
unique: true
},
password: String,
workers: [WorkerSchema]
});
var TopicSchema = new Schema({
id: ObjectId,
title: String,
moderator: UserSchema,
posts: [PostSchema]
});
var Topic = mongoose.model('Topic', TopicSchema);
app.post('/topics', requireLogin, function(req, res) {
User.findOne({"email": req.session.user.email}, function(err, user) {
if (user.role == "moderator" || user.role == "admin") {
var topic = new Topic({
title: req.body.title,
moderator: req.session.user,
posts: []
});
topic.save(function(err) {
if (err) console.log(err);
res.status(204).end();
});
}
});
});
My issue is this... When I POST a topic to /topics, it works the first time, populating the topics collection with one item. But then, when I POST to /topics again, from the same user, I get an E11000 MongoError that looks like this:
message: 'E11000 duplicate key error index: MY_MONGO_DB.topics.$moderator.email_1 dup key: { : "myuser#example.com" }'
I know that removing the 'unique: true' property from the email field of UserSchema would fix this issue, but I don't want to remove that uniqueness property since I use it elsewhere in my code to ensure that users are unique by email.
Is there any way around this? In other words, is there any way to keep the 'unique: true' property and also retain the ability of users to be able to post multiple topics without triggering the E11000 error?
What you did was to embed the user. In your database, the resulting document would look something like
{
...
moderator: {..., email: "john#example.com"}
}
Which, of course, would violate the unique constraint if you have the same person as a moderator twice.
What you should do instead is to reference the user in your schema:
var user = mongoose.model('User', UserSchema);
var TopicSchema = new Schema({
id: ObjectId,
title: String,
moderator: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
posts: [PostSchema]
});

return all unique indexes errors while saving

I have to following code:
var UserSchema = mongoose.Schema({
email: {
type: String,
unique: true
},
username: {
type: String,
unique: true
}
});
var User = db.model('User', UserSchema);
var user = new User();
user.email = 'some#email.com'
user.username = 'peter'
user.save(function(err){
if (err) return console.log(err)
console.log('user saved')
})
On the first run it shows user saved which is totally fine. On the second run it gives me
{ [MongoError: E11000 duplicate key error index: node-login.users.$username_1 dup key: { : "peter" }]
name: 'MongoError',
err: 'E11000 duplicate key error index: node-login.users.$username_1 dup key: { : "peter" }',
code: 11000,
n: 0,
lastOp: 0,
connectionId: 1455732,
ok: 1 }
What about the email? It is also a duplicate and should return an error. If only one error is thrown each time, why is it the username and not email? email is above username in the schema. How does mongoose decide about what duplicate to check/return first?
It's not Mongoose that's doing this, it's MongoDB. Which one of the two duplicate fields that's flagged is likely undefined. I assume it's simply throwing the error as soon as the first index it checks fails the uniqueness test.
If you need more information than what's provided in the error, you'll need to query for all potential duplicate fields separately.

Resources