E11000 index d'erreur de clé en double dans mangouste mongodb

229

Voici mon userschéma dans le user.jsmodèle -

var userSchema = new mongoose.Schema({
    local: {
        name: { type: String },
        email : { type: String, require: true, unique: true },
        password: { type: String, require:true },
    },
    facebook: {
        id           : { type: String },
        token        : { type: String },
        email        : { type: String },
        name         : { type: String }
    }
});

var User = mongoose.model('User',userSchema);

module.exports = User;

Voici comment je l'utilise dans mon contrôleur -

var user = require('./../models/user.js');

Voici comment je l'enregistre dans la base de données -

user({'local.email' : req.body.email, 'local.password' : req.body.password}).save(function(err, result){
    if(err)
        res.send(err);
    else {
        console.log(result);
        req.session.user = result;
        res.send({"code":200,"message":"Record inserted successfully"});
    }
});

Erreur -

{"name":"MongoError","code":11000,"err":"insertDocument :: caused by :: 11000 E11000 duplicate key error index: mydb.users.$email_1  dup key: { : null }"} 

J'ai vérifié la collection db et aucune entrée en double n'existe, faites-moi savoir ce que je fais mal?

FYI - req.body.emailet req.body.passwordrécupèrent des valeurs.

J'ai aussi vérifié ce post mais sans aide STACK LINK

Si j'ai supprimé complètement, il insère le document, sinon il génère une erreur "Duplicate" même si j'ai une entrée dans le local.email

Trialcoder
la source
1
Eu la même erreur! Pendant le développement, nous avons désactivé l'indexation automatique et utilisons des noms / clés de schéma en minuscules. Nous avons décidé plus tard d'utiliser TitleCase à la place, mais nous n'avons pas réussi à mettre à jour nos noms d'index (c'est-à-dire: titleCase au lieu de TitleCase). Donc, lorsque nous avons activé l'indexation, nous avons eu cette erreur. Il a fallu un peu de temps pour le comprendre. Vous voudrez vous assurer que tous les noms / clés sont nommés exactement partout.
Jeach
6
J'ai eu la même erreur et définir le modèle mangouste unique: falsen'a eu aucun impact. J'ai réalisé que je devais d'abord laisser tomber la table et ensuite ça marcherait. Vous pouvez faire quelque chose comme db.whateverthecollection.drop({}). Attention, il supprime la collection.
Pere
1
_id: mongoose.Types.ObjectId add car un identifiant unique est requis
Mayank Pandav

Réponses:

241

Le message d'erreur indique qu'il existe déjà un enregistrement avec null comme e-mail. En d'autres termes, vous avez déjà un utilisateur sans adresse e-mail.

La documentation pertinente pour cela:

Si un document n'a pas de valeur pour le champ indexé dans un index unique, l'index stockera une valeur nulle pour ce document. En raison de la contrainte unique, MongoDB n'autorisera qu'un seul document qui n'a pas le champ indexé. S'il existe plusieurs documents sans valeur pour le champ indexé ou s'il manque le champ indexé, la génération d'index échouera avec une erreur de clé en double.

Vous pouvez combiner la contrainte unique avec l'index clairsemé pour filtrer ces valeurs nulles à partir de l'index unique et éviter l'erreur.

index uniques

Les index épars ne contiennent que des entrées pour les documents qui ont le champ indexé, même si le champ d'index contient une valeur nulle.

En d'autres termes, un index clairsemé est correct avec plusieurs documents ayant tous des nullvaleurs.

index clairsemés


Des commentaires:

Votre erreur indique que la clé est nommée, mydb.users.$email_1ce qui me fait penser que vous avez un index sur les deux users.emailet users.local.email(le premier étant ancien et inutilisé pour le moment). La suppression d'un champ d'un modèle Mongoose n'affecte pas la base de données. Vérifiez mydb.users.getIndexes()si c'est le cas et supprimez manuellement l'index indésirable avec mydb.users.dropIndex(<name>).

RickN
la source
1
Je viens de supprimer ce document nul et cela a fonctionné :) +1 ..thx pour l'aide
Trialcoder
70
Votre erreur indique que la clé est nommée, mydb.users.$email_1ce qui me fait penser que vous avez un index sur les deux users.emailet users.local.email(le premier étant ancien et inutilisé pour le moment). La suppression d'un champ d'un modèle Mongoose n'affecte pas la base de données. Vérifiez mydb.users.getIndexes()si c'est le cas et supprimez manuellement l'index indésirable avec mydb.users.dropIndex(<name>).
RickN
17
Ou utilisez db.users.dropIndexes()si vous effectuez plusieurs changements d'index
cs_stackX
1
C'était un problème pour moi lorsque j'utilisais le plugin mongoose passport-local-mongoose sans définir de nom d'utilisateur pour les nouveaux utilisateurs.
sshow
1
C'est une question ou une perspective ou peut-être même une opinion, @titoih - est nul ou l'absence d'une valeur une valeur comme une autre ou est-ce un cas spécial? «a @ bc» et «a @ bc» sont les mêmes, «rien» et «rien» sont-ils également les mêmes? Avec un index non clairsemé, la réponse est "oui" dans MongoDB. D'autres bases de données (comme MySQL) diraient «non».
RickN
65

Si vous êtes toujours dans votre environnement de développement, je laisserais tomber la base de données entière et recommencerais avec votre nouveau schéma.

Depuis la ligne de commande

 mongo
use dbName;
db.dropDatabase();
exit
Meule
la source
47
Je pense que cette solution est très agressive, je pense que c'est suffisant avec db.collection.dropIndexes()comme l'a dit
cs_stackX
2
@JorgeGarza J'ai eu le même problème. Je viens de laisser tomber la collection et tout a bien fonctionné après cela.
Sandip Subedi
J'ai accidentellement initialisé la collection avec un identifiant unique pour deux de mes domaines. Plus tard, lorsque j'ai voulu ajouter plusieurs documents avec le même identifiant, cela ne m'a pas permis tant que je n'ai pas supprimé la collection et n'y ai pas accédé de nouveau.
Meir Snyder
1
Si vous êtes nouveau dans votre développement, c'est une bonne occasion d'expérimenter et de comprendre comment résoudre ce problème ... plutôt que de rencontrer ce problème une fois que vous avez déjà des gigaoctets de données utilisateur stockées
Janac Meena
Le commentaire de @JorgeGarza est logique. Les index supprimés seront à nouveau reconstruits par le fichier de schéma au redémarrage du serveur. Cela a également fonctionné.
retr0
26

Vérifiez les index de collection.

J'ai eu ce problème en raison d'index obsolètes dans la collection des champs, qui devraient être stockés par un nouveau chemin différent.

Mongoose ajoute un index lorsque vous spécifiez un champ comme unique.

Yegor
la source
22

Eh bien, fondamentalement, cette erreur signifie que vous aviez un index unique sur un champ particulier, par exemple: "email_address", donc mongodb attend une valeur d'adresse e-mail unique pour chaque document de la collection.

Disons que, plus tôt dans votre schéma, l'index unique n'a pas été défini, puis vous avez inscrit 2 utilisateurs avec la même adresse e-mail ou sans adresse e-mail (valeur nulle).

Plus tard, vous avez vu qu'il y avait une erreur. vous essayez donc de le corriger en ajoutant un index unique au schéma. Mais votre collection a déjà des doublons, donc le message d'erreur indique que vous ne pouvez pas réinsérer une valeur en double.

Vous avez essentiellement trois options:

  1. Déposez la collection

    db.users.drop();

  2. Recherchez le document qui a cette valeur et supprimez-le. Disons que la valeur était nulle, vous pouvez la supprimer en utilisant:

    db.users.remove({ email_address: null });

  3. Supprimez l'index unique:

    db.users.dropIndex(indexName)

J'espère que cela a aidé :)

Daksh Miglani
la source
20

Je veux expliquer la réponse / solution à cela comme je l'explique à un enfant de 5 ans, afin que tout le monde puisse comprendre.

J'ai une application, je veux que les gens s'inscrivent avec leur email, mot de passe et numéro de téléphone. Dans ma base de données MongoDB, je veux identifier les personnes uniquement en fonction de leur numéro de téléphone et de leur adresse e-mail - cela signifie donc que le numéro de téléphone et l'e-mail doivent être uniques pour chaque personne.

Cependant, il y a un problème: j'ai réalisé que tout le monde a un numéro de téléphone mais pas tout le monde a une adresse e-mail.

Ceux qui n'ont pas d'adresse e-mail m'ont promis qu'ils auront une adresse e-mail la semaine prochaine. Mais je veux qu'ils soient enregistrés de toute façon - je leur dis donc de procéder à l'enregistrement de leurs numéros de téléphone alors qu'ils laissent le champ de saisie e-mail vide.

Ils le font.

Ma base de données A BESOIN d'un champ d'adresse e-mail unique - mais j'ai beaucoup de gens avec 'null' comme adresse e-mail. Je vais donc dans mon code et je dis à mon schéma de base de données d'autoriser les champs d'adresse e-mail vides / nuls que je remplirai plus tard avec des adresses e-mail uniques lorsque les personnes qui ont promis d'ajouter leurs e-mails à leur profil la semaine prochaine.

Donc c'est maintenant un gagnant-gagnant pour tout le monde (mais vous; -]): les gens s'inscrivent, je suis heureux d'avoir leurs données ... et ma base de données est heureuse parce qu'elle est bien utilisée ... mais qu'en est-il de vous? Je dois encore vous donner le code qui a fait le schéma.

Voici le code: REMARQUE: La propriété clairsemée dans le courrier électronique, indique à ma base de données d'autoriser les valeurs nulles qui seront ultérieurement remplies avec des valeurs uniques.

var userSchema = new mongoose.Schema({
  local: {
    name: { type: String },
    email : { type: String, require: true, index:true, unique:true,sparse:true},
    password: { type: String, require:true },
  },
  facebook: {
    id           : { type: String },
    token        : { type: String },
    email        : { type: String },
    name         : { type: String }
  }
});

var User = mongoose.model('User',userSchema);

module.exports = User;

J'espère que je l'ai bien expliqué. Joyeux codage / piratage NodeJS!

Daggie Blanqx - Douglas Mwangi
la source
si vous voulez un sparseindex et une uniquevalidation, et que vous avez d'autres champs qui ne sont pas obligatoires, vous devrez utiliser l' partialFilterExpressionoption. Voir cette réponse stackoverflow.com/a/34600171/728287
Gianfranco P.
4

Dans cette situation, connectez-vous à Mongo pour trouver l'index que vous n'utilisez plus (dans le cas de OP 'email'). Sélectionnez ensuite Drop Index entrez la description de l'image ici

bumsoverboard
la source
3

Voici mon expérience intéressante:

Dans le schéma «Utilisateur», j'ai défini «nom» comme clé unique, puis j'ai exécuté une exécution qui, je pense, avait configuré la structure de la base de données.

Ensuite, j'ai changé la clé unique en «nom d'utilisateur» et je n'ai plus transmis la valeur «nom» lorsque j'ai enregistré les données dans la base de données. Ainsi, le mongodb peut définir automatiquement la valeur «nom» du nouvel enregistrement comme null, qui est une clé en double. J'ai essayé la clé «nom» définie comme clé non unique {name: {unique: false, type: String}} dans le schéma «Utilisateur» afin de remplacer le paramètre d'origine. Cependant, cela n'a pas fonctionné.

Enfin, j'ai fait ma propre solution:

Définissez simplement une valeur de clé aléatoire qui ne sera probablement pas dupliquée sur la clé «nom» lorsque vous sauvegardez votre enregistrement de données. La méthode Simply Math '' + Math.random() + Math.random() crée une chaîne aléatoire.

Kobe Luo
la source
12
Je ne pense pas que ce soit une solution valable, vous masquez simplement le problème.
Rick
Moche mais pragmatique
Anthony
3

J'ai eu le même problème. J'ai essayé différentes méthodes de débogage. J'ai essayé de supprimer la collection et cela a bien fonctionné après cela. Bien que ce ne soit pas une bonne solution si votre collection contient de nombreux documents. Mais si vous êtes au début du développement, essayez de supprimer la collection.

db.users.drop();
Sandip Subedi
la source
2

En effet, il existe déjà une collection du même nom avec la configuration .. Supprimez simplement la collection de votre mongodb via mongo shell et réessayez.

db.collectionName.remove ()

maintenant exécutez votre application, cela devrait fonctionner

Ignace Andrew
la source
2

J'ai eu un problème similaire et j'ai réalisé que par défaut mongo ne prend en charge qu'un seul schéma par collection. Enregistrez votre nouveau schéma dans une autre collection ou supprimez les documents existants avec le schéma incompatible dans votre collection actuelle. Ou trouvez un moyen d'avoir plus d'un schéma par collection.

Embedded_Mugs
la source
2

J'ai également fait face à ce problème et je l'ai résolu. Cette erreur montre que l'e-mail est déjà présent ici. Il vous suffit donc de supprimer cette ligne de votre attribut Model for email.

unique: true

Cela pourrait être possible même si cela ne fonctionne pas. Il suffit donc de supprimer la collection de votre MongoDB et de redémarrer votre serveur.

Inamur Rahman
la source
1

J'ai eu ce même problème lorsque j'avais la configuration suivante dans ma config / models.js

module.exports.models = {
  connection: 'mongodb',
  migrate: 'alter'
}

Changer la migration de 'alter' en 'safe' l'a corrigé pour moi.

module.exports.models = {
  connection: 'mongodb',
  migrate: 'safe'
}
Jam Risser
la source
1

même problème après la suppression des propriétés d'un schéma après première construction de certains index lors de l'enregistrement. la suppression d'une propriété du schéma conduit à une valeur nulle pour une propriété non existante, qui avait toujours un index. supprimer l'index ou commencer avec une nouvelle collection à partir de zéro aide ici.

remarque: le message d'erreur vous conduira dans ce cas. il a un chemin qui n'existe plus. dans mon cas, l'ancien chemin était ... $ uuid_1 (c'est un index!), mais le nouveau est .... * priv.uuid_1

chhtm
la source
1

J'ai eu le même problème lorsque j'ai essayé de modifier le schéma défini à l'aide de mangoose. Je pense que le problème est dû à la raison pour laquelle un processus sous-jacent est créé lors de la création d'une collection, comme la description des indices qui sont cachés à l'utilisateur (du moins dans mon cas). et recommencez.

Rahul P
la source
0

J'ai eu le même problème. Le problème est que j'ai supprimé un champ du modèle. Quand j'ai laissé tomber db, ça corrige

user86168
la source
0

pour les futurs développeurs, je recommande de supprimer l'index dans INDEX TAB à l'aide de la boussole ... ceci NE SUPPRIME AUCUN document de votre collection Gérer les index

Edgar Olivar
la source
-3

Modifiez le nom de la collection s'il existe déjà dans la base de données, il affichera une erreur. Et si vous avez donné une propriété comme unique, la même erreur se produira.

arul mb
la source
-4

Eu le même problème, je l'ai résolu en supprimant l' uniqueattribut sur la propriété.

Trouvez simplement un autre moyen de valider ou de vérifier les valeurs de propriété uniques pour votre schéma.

davyCode
la source
Vous devez fournir un exemple avec votre solution.
Josh Adams
Tout d'abord, l'effacement de la collection et / ou la suppression de la collection entière de la base de données mongo a fonctionné, mais c'était une solution temporaire. La création d'un autre enregistrement avec des valeurs similaires, même s'ils avaient des identifiants différents, donnait toujours une erreur de clé en double E11000. Je voulais autoriser les valeurs en double pour cette propriété, j'ai donc simplement supprimé l'attribut unique.
davyCode
-7

Veuillez effacer la collection ou supprimer la collection entière de la base de données MongoDB et réessayer plus tard.

Vittal Kamkar
la source