问题
I've done a lot of research to find this answer to my problem, but I haven't discovered anything. Feel free to attach a link if I missed the answer.
I did find this solution, but I'm not exactly sure how it might apply to this situation: E11000 duplicate key error index in mongodb mongoose
I'm trying to connect my Express.js, MongoDB, Passport.js app to Mongo-Atlas. I have my Atlas cluster set up and accepting new Users from my localhost and using Google Oauth 2.0, however, when I try to register or log-in using Facebook, I get the following error.
MongoError: E11000 duplicate key error collection: userDB.users index: username_1 dup key: { username: null }
Could it have something to do with this?
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
It worked when connected to my localhost MongoDB, and as I stated I'm having trouble finding a solution.
passport.use(new FacebookStrategy({
clientID: process.env.FBAPPID,
clientSecret: process.env.FBSECRET,
callbackURL: "http://localhost:3000/auth/facebook/secrets"
},
function(accessToken, refreshToken, profile, cb) {
console.log(profile);
User.findOrCreate({ facebookId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
app.get('/auth/facebook', passport.authenticate('facebook'));
app.get('/auth/facebook/secrets',
passport.authenticate('facebook', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/secrets');
});
UPDATE
So I've found some documentation about dropping Indexes on MongoDB However that wasn't entirely clear, so I also found an article Dropping Existing Indexes So I implemented the code into my own app.js file.
// Dropping an Index in MongoDB
User.collection.dropIndex({name : "username_1"}, function(err, res) {
if (err) {
console.log('Error in dropping index!', err);
}
});
I've been dropping the Database in between testing to see if that works, but I've been getting thrown this error everything, no matter how I alter the code to try and fix it!
{ _bsontype: 'Timestamp', low_: 1, high_: 1586408833 },
ok: 0,
errmsg: `can't find index with key: { name: "username_1" }`,
code: 27,
codeName: 'IndexNotFound',
'$clusterTime': {
clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1586408833 },
signature: { hash: [Binary], keyId: [Long] }
},
name: 'MongoError',
[Symbol(mongoErrorContextSymbol)]: {}
}
And yet when I run db.users.getIndexes()
in my Mongo Shell connected to my Atlas server. Sure enough there it is! I even tried using dropIndexes
and it only dropped the email index! I am so frustrated with this!
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "userDB.users"
},
{
"v" : 2,
"key" : {
"email" : 1
},
"name" : "email_1",
"ns" : "userDB.users",
"background" : true
},
{
"v" : 2,
"unique" : true,
"key" : {
"username" : 1
},
"name" : "username_1",
"ns" : "userDB.users",
"background" : true
}
]
回答1:
You have a unique index defined on username but your code is not inserting a username (potentially because the username is not getting retrieved from the authentication provider as you are expecting). This causes multiple documents with the same value in the username filed (null).
If your users are supposed to have a username, you need to debug your code to figure out why it's not retrieving the username or passing it to MongoDB. If username is optional, remove the unique index on it.
回答2:
It finally clicked! I went into the indexes tab on Atlas and deleted the required username index. Thank you for your help @oleg For some reason I couldn't find this explanation online!
Update
So deleting the index from Mongo-Atlas only temporarily solves the problem. I believe I figured out how to drop the index from my code, but I dropped it from Mongo shell already, which has seemed to solve the problem as well. So I'll provide both commands:
const User = new mongoose.model('User', userSchema);
User.collection.indexExists({ "username" : 1 }, function(err, results){
console.log(results);
if ( results === true) {
// Dropping an Index in MongoDB
User.collection.dropIndex( { "username" : 1 } , function(err, res) {
if (err) {
console.log('Error in dropping index!', err);
}
});
} else {
console.log("Index doesn't exisit!");
}
});
In Mongo Shell, go into your DB and run this command:
db.users.dropIndex( { "username" : 1 } );
To confirm, run:
db.users.getIndexes()
So many hours of research trying to solve this problem! I hope it helps you!
回答3:
Go to your atlas cluster then open collections and then open indexes
and then delete username_1 index manually.
来源:https://stackoverflow.com/questions/61091800/setting-up-facebook-authentication-with-mongodb-atlas-and-passport-js