web-dev-qa-db-fra.com

Mongoose Index unique ne fonctionne pas!

J'essaie de laisser MongoDB détecter une valeur en double en fonction de son index. Je pense que cela est possible dans MongoDB, mais à travers le wrapper Mongoose, les choses semblent cassées. Donc, pour quelque chose comme ça:

User = new Schema ({
  email: {type: String, index: {unique: true, dropDups: true}}
})

Je peux sauver 2 utilisateurs avec le même email. Zut.

Le même problème a été exprimé ici: https://github.com/LearnBoost/mongoose/issues/56 , mais ce fil est ancien et ne mène nulle part.

Pour l'instant, j'appelle manuellement la base de données pour rechercher l'utilisateur. Cet appel n’est pas coûteux, car "email" est indexé. Mais il serait toujours agréable de le laisser être traité de manière native.

Est-ce que quelqu'un a une solution à cela?

69
foobar

Oops! Il suffit de redémarrer Mongo.

71
foobar

Oops! Il suffit de redémarrer Mongo.

Et ré-index aussi!

En test, je viens de faire un:

mongo <db-name>
> db.dropDatabase()

Cependant, si vous y avez des données importantes, il vous suffit probablement de:

mongo <db-name>
> db.<collection-name>.reIndex()
38
jpillora

J'ai rencontré le même problème: j'ai ajouté la contrainte unique pour le champ email à notre UserSchema après avoir déjà ajouté des utilisateurs à la base de données, et j'étais toujours capable de sauvegarder des utilisateurs avec des emails en dupe. J'ai résolu ceci en procédant comme suit: 

1) Supprimez tous les documents de la collection d'utilisateurs.

2) Depuis le shell mongo, exécutez la commande: db.users.createIndex({email: 1}, {unique: true})

En ce qui concerne l'étape 1, notez que, d'après les documents de Mongo: 

MongoDB ne peut pas créer un index unique sur le (s) champ (s) d'index spécifié (s) si la collection contient déjà des données qui violeraient la contrainte unique pour l'index.

https://docs.mongodb.com/manual/core/index-unique/

13
Neil Strain

Ce problème se produit également si vous avez laissé des doublons dans Mongo. Mongoose essaiera de les créer dans Mongo au démarrage de votre application.

Pour éviter cela, vous pouvez gérer cette erreur de la manière suivante: 

yourModel.on('index', function(err) {
  if (err?) {
    console.error err
  }
);
11
Pierre Maoui

Ok, j’ai pu résoudre ce problème à partir du mongoshell en ajoutant l’index sur le champ et en définissant la propriété unique:

db.<collectionName>.ensureIndex({fieldName: 1}, {unique: true});

Shell devrait répondre comme suit:

{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

Maintenant, pour tester rapidement depuis le Mongoshell:

var doc = {fieldName: 'abc'};
db.<collectionName>.insert(doc)

Devrait donner: WriteResult ({"nInserted": 1})

Mais en répétant encore:

db.<collectionName>.insert(doc)

Va donner:

WriteResult({
    "nInserted" : 0,
    "writeError" : {
        "code" : 11000,
        "errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: fuelConsumption.users.$email_1  dup key: { : \"[email protected]\" }"
    }
})
9
sigman.pl

Selon la documentation: https://docs.mongodb.com/v2.6/tutorial/modify-an-index/

Pour modifier un index existant, vous devez supprimer et recréer l'index.

NE PAS REDÉMARRER MONGO! 

1 - déposer la collection

db.users.drop()

2 - réindexer la table

db.users.ensureIndex({email: 1, type: 1}, {unique: true})
4
Damien Romito

J'ai fait quelque chose comme ça:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const FooSchema = new Schema({
   name: { type: String, required: true, index: true, unique: true }
});

const Foo = mongoose.model('Foo', FooSchema);

Foo.createIndexes();

module.exports = Foo

J'ai ajouté la Foo.createIndexes() ligne b.c. Je recevais l'avertissement de dépréciation suivant lors de l'exécution du code:

(node:21553) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.

Je ne suis pas sûr que Foo.createIndexes() soit asynchrone, mais les données AFAIK semblent bien fonctionner

4
solstice333

vérifie que autoIndex dans le schéma est true, il peut être défini sur false (valeur par défaut) lorsque vous utilisez les options mongoose.connect

1
Lee Quinze

Si la table/collection est vide, créez un index unique pour le champ:

db.<collection_name>.createIndex({'field':1}, {unique: true})

Si la table/collection n'est pas vide, alors supprimez la collection et créez un index:

db.<collection_name>.drop()
db.<collection_name>.createIndex({'field':1}, {unique: true})

Maintenant, redémarrez mongoDB.

1
Rakin Afser

Vous pouvez également résoudre ce problème en supprimant l'index.

supposons que vous souhaitiez supprimer l'index unique de la collection users et du champ username, tapez ceci:

db.users.dropIndex('username_1');

1
Ademola Adegbuyi

Dernière réponse: il n'est pas du tout nécessaire de redémarrer mongodb, Si la collection a déjà les mêmes noms de noms, mangouste ne recréera pas à nouveau vos index, donc, supprimez d'abord les index existants de la collection, vous exécutez mangouste, il va créer un nouvel index, processus ci-dessus a résolu mon problème.

1
chen Jacky

Vous pouvez définir votre schéma comme

User = new Schema ({
  email: {
      type: String,
      unique: true
  }
})

Mais peut-être que cela ne fonctionnera pas quand il y a déjà un document et après cela, vous avez changé le schéma de l'utilisateur. Vous pouvez créer un index sur le courrier électronique pour cette collection d'utilisateurs si vous ne souhaitez pas supprimer la collection. En utilisant cette commande, vous pouvez créer un index sur un courrier électronique.

db.User.createIndex({email:1},{unique: true})

Ou vous pouvez simplement supprimer la collection et ajouter l'utilisateur à nouveau.
Pour déposer la collection, vous pouvez entrer ceci:

db.User.drop()
0
Pulkit Aggarwal

J'ai fait face au même problème pendant un certain temps et ai fait beaucoup de recherches et la solution pour moi était la fonction createIndexes().

Je souhaite que cela aide.

donc le code sera comme ça.

User = new Schema ({
   email: {type: String, unique: true}
});
User.createIndexes();
0
Samir Hosny

Lorsque j'ai rencontré ce problème, j'ai essayé de supprimer la base de données, de redémarrer le serveur (nodemon) plusieurs fois et aucune des astuces ne fonctionnait du tout. J'ai trouvé le travail suivant autour de Robo 3T:

  1. Dans Robo 3T, double-cliquez sur la base de données pour ouvrir les collections.
  2. Ouvrez les collections pour révéler la collection en question. Assurez-vous que vos collections sont vides, pour commencer
  3. Cliquez avec le bouton droit sur le dossier Indexes. Par défaut, vous verrez le _id_ comme valeur par défaut. Maintenant, choisissez Ajouter un index
  4. Choisissez un nom, par exemple email pour le champ de courrier électronique, par exemple
  5. Fournissez les clés au format JSON. Par exemple

    {
       "email": 1
    }
    
  6. Cliquez sur la case à cocher Unique

  7. Sauvegarder

Cela garantira qu'aucun e-mail en double n'est enregistré dans MongoDB.

0
Balepur