it-swarm.com.de

Mongoose Einzigartiger Index funktioniert nicht!

Ich versuche, MongoDB einen doppelten Wert basierend auf seinem Index erkennen zu lassen. Ich denke, das ist in MongoDB möglich, aber durch den Mongoose-Wrapper scheinen die Dinge kaputt zu sein. Also für so etwas:

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

Ich kann 2 Benutzer mit derselben E-Mail speichern. Verdammt.

Das gleiche Problem wurde hier zum Ausdruck gebracht: https://github.com/LearnBoost/mongoose/issues/56 , aber dieser Thread ist alt und führt zu nichts.

Momentan rufe ich manuell die Datenbank an, um den Benutzer zu finden. Dieser Anruf ist nicht teuer, da "E-Mail" indiziert ist. Es wäre aber trotzdem schön, wenn man es nativ handhaben lassen würde.

Hat jemand eine Lösung dafür?

69
foobar

Hoppla! Sie müssen nur den Mongo neu starten.

71
foobar

Hoppla! Sie müssen nur den Mongo neu starten.

Und auch neu indexieren!

Beim Testen habe ich gerade Folgendes gemacht:

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

Wenn Sie jedoch wichtige Daten haben, müssen Sie wahrscheinlich nur:

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

Ich bin auf das gleiche Problem gestoßen: Ich habe die eindeutige Einschränkung für das Feld email zu unserer UserSchema hinzugefügt, nachdem ich bereits Benutzer zur Datenbankbibliothek hinzugefügt habe, und konnte trotzdem Benutzer mit Dupe-E-Mails speichern. Ich habe das folgendermaßen gelöst: 

1) Entfernen Sie alle Dokumente aus der Benutzersammlung.

2) Führen Sie in der Mongo-Shell den folgenden Befehl aus: db.users.createIndex({email: 1}, {unique: true})

Beachten Sie in Schritt 1 Folgendes aus den Unterlagen von Mongo: 

MongoDB kann für die angegebenen Indexfelder keinen eindeutigen Index erstellen, wenn die Sammlung bereits Daten enthält, die gegen die eindeutige Einschränkung für den Index verstoßen würden.

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

13
Neil Strain

Dieses Verhalten tritt auch dann auf, wenn Sie einige Kopien in Mongo hinterlassen haben. Mongoose versucht, sie in Mongo zu erstellen, wenn Ihre Anwendung gestartet wird.

Um dies zu verhindern, können Sie diesen Fehler folgendermaßen behandeln: 

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

Ok, ich konnte dies von der Mongoshell aus lösen, indem ich den Index für das Feld hinzufügte und die eindeutige Eigenschaft setzte:

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

Shell sollte auf diese Weise reagieren:

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

Jetzt schnell von der Mongoshell aus testen:

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

Sollte geben: WriteResult ({"nInserted": 1})

Aber wenn wir es noch einmal wiederholen:

db.<collectionName>.insert(doc)

Wird geben:

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

Mungo ist etwas locker, wenn es darum geht, eindeutige Indizes von der Anwendungsebene aus zu erzwingen. Aus diesem Grund ist es vorzuziehen, entweder Ihre eindeutigen Indizes mit dem mongo cli aus der Datenbank selbst zu erzwingen oder mongoose explizit mitzuteilen, dass Sie den unique -Index ernst meinen, indem Sie direkt nach Ihrem UserSchema die folgende Codezeile schreiben:

UserSchema.index({ username: 1, email: 1 }, { unique: true});

Dadurch wird der eindeutige Index für die Felder username und email in Ihrem UserSchema erzwungen. Prost.

5
moeabdol

Laut Dokumentation: https://docs.mongodb.com/v2.6/tutorial/modify-an-index/

Um einen vorhandenen Index zu ändern, müssen Sie den Index löschen und neu erstellen.

MONGO NICHT NEU STARTEN! 

1 - lassen Sie die Sammlung fallen

db.users.drop()

2 - Indizieren Sie die Tabelle neu

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

Ich habe so etwas gemacht:

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

Ich habe die Foo.createIndexes()-Zeile b.c. hinzugefügt. Beim Ausführen des Codes wurde folgende Warnung angezeigt:

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

Ich bin nicht sicher, ob Foo.createIndexes() asynchron ist, aber AFAIK scheint gut zu funktionieren

4
solstice333

Mungo-Unique-Validator

Wie man dieses Plugin benutzt:

1) npm install --save mongoose-unique-validator

2) Folgen Sie in Ihrem Schema dieser Anleitung:

// declare this at the top
var mongoose = require('mongoose');
var uniqueValidator = require('mongoose-unique-validator');

// exampleSchema = mongoose.Schema({}) etc...

exampleSchema.plugin(uniqueValidator);

// module.exports = mongoose.model(...) etc....

3) Mungomethoden

Wenn Sie Methoden wie findOneAndUpdate verwenden, müssen Sie dieses Konfigurationsobjekt übergeben:

{ runValidators: true, context: 'query' }

ie. User.findOneAndUpdate(
      { email: '[email protected]' },
      { email: '[email protected]' },
      { runValidators: true, context: 'query' },
      function(err) {
        // ...
    }

4) zusätzliche Optionen

  1. groß- und Kleinschreibung wird nicht berücksichtigt

    verwenden Sie in Ihrem Schema die Option uniqueCaseInsensitive

    ie. email: { type: String, index: true, unique: true, required: true, uniqueCaseInsensitive: true }

  2. benutzerdefinierte Fehlermeldungen

    ie. exampleSchema.plugin(uniqueValidator, { message: 'Error, expected {PATH} to be unique.' });

Jetzt können Sie die eindeutige Eigenschaft zu Ihren Schemas hinzufügen/löschen, ohne sich Gedanken über einen Neustart von Mongo, das Löschen von Datenbanken oder das Erstellen von Indizes machen zu müssen.

Vorsichtsmaßnahmen (aus den Dokumenten):

Da wir uns auf asynchrone Vorgänge verlassen, um zu überprüfen, ob ein Dokument in der Datenbank vorhanden ist, können zwei Abfragen gleichzeitig ausgeführt werden, beide erhalten 0 zurück und beide fügen sie in MongoDB ein.

Außer dem automatischen Sperren der Sammlung oder dem Erzwingen einer einzelnen Verbindung gibt es keine echte Lösung.

Für die meisten unserer Benutzer ist dies kein Problem, aber ein Edge-Fall, dessen Sie sich bewusst sein sollten.

3
Isaac Pak

vergewissern Sie sich, dass der AutoIndex im Schema "true" ist. Wenn Sie die Optionen "mongoose.connect" verwenden, wird möglicherweise "false" (Standardwert "true") festgelegt

1
Lee Quinze

Wenn die Tabelle/Sammlung leer ist, erstellen Sie einen eindeutigen Index für das Feld:

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

Wenn die Tabelle/Sammlung nicht leer ist, löschen Sie die Sammlung und erstellen Sie einen Index:

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

Starten Sie nun mongoDB neu.

1
Rakin Afser

Sie können dieses Problem auch beheben, indem Sie den Index löschen.

angenommen, Sie möchten den eindeutigen Index aus der Auflistung users und dem Feld username entfernen, geben Sie Folgendes ein:

db.users.dropIndex('username_1');

1

Neueste Antwort: Es ist nicht nötig, mongodb neu zu starten. Wenn Colleciton bereits dieselben Namensindizes hat, erstellt mongoose Ihre Indizes nicht erneut. Legen Sie also zuerst die vorhandenen Indizes von colleciton, Und jetzt, wann ab Wenn Sie Mungo laufen lassen, wird ein neuer Index erstellt. Der obige Prozess hat mein Problem gelöst.

1
chen Jacky

Wenn Sie die Option autoIndex: false In der Verbindungsmethode wie folgt verwenden:

mongoose.connect(CONNECTION_STRING, { autoIndex: false });

Versuchen Sie das zu entfernen. Wenn das nicht funktioniert, versuchen Sie mongodb neu starten wie in diesem Thread vorgeschlagen.

0
Rafael Mejía

Sie können Ihr Schema als definieren

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

Aber möglicherweise funktioniert dies nicht, wenn bereits ein Dokument vorhanden ist und Sie anschließend das Schema des Benutzers geändert haben. Sie können einen Index für diese Benutzersammlung per E-Mail erstellen, wenn Sie die Sammlung nicht löschen möchten. Mit diesem Befehl können Sie einen Index für E-Mails erstellen.

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

Oder Sie können die Sammlung einfach löschen und den Benutzer erneut hinzufügen.
Zum Löschen der Sammlung können Sie Folgendes eingeben:

db.User.drop()
0
Pulkit Aggarwal

Ich hatte eine Weile mit dem gleichen Problem zu kämpfen und habe viel gesucht. Die Lösung für mich war die Funktion createIndexes().

Ich wünschte, das hilft.

so wird der Code sein.

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

Als ich auf dieses Problem stieß, habe ich mehrmals versucht, die Datenbank zu löschen, den Server (nodemon) neu zu starten, und keiner der Tricks hat überhaupt nicht funktioniert. Durch Robo 3T habe ich die folgende Lösung gefunden:

  1. Doppelklicken Sie im Robo 3T auf die Datenbank, um die Sammlungen zu öffnen
  2. Öffnen Sie die Sammlungen, um die betreffende Sammlung anzuzeigen. Stellen Sie zunächst sicher, dass Ihre Sammlungen leer sind
  3. Klicken Sie mit der rechten Maustaste auf den Indexordner. Standardmäßig wird der _id_ als Standard angezeigt. Wählen Sie nun Index hinzufügen
  4. Wählen Sie einen Namen, z. B. email für das E-Mail-Feld
  5. Stellen Sie Schlüssel als JSON bereit. Zum Beispiel

    {
       "email": 1
    }
    
  6. Klicken Sie auf das Kontrollkästchen Eindeutig

  7. Sparen

Dadurch wird sichergestellt, dass keine doppelten E-Mails in der MongoDB gespeichert werden.

0
Balepur