Eindeutiger Index in MongoDB

Tahseen Tauseef 12 Oktober 2023
  1. Eindeutiger Index in MongoDB
  2. Verhalten des eindeutigen Index in MongoDB
  3. Validieren Sie eindeutige E-Mails mit Mongoose
Eindeutiger Index in MongoDB

In diesem Tutorial erfahren Sie mehr über eindeutige Indizes, einschließlich was sie sind und wie sie in MongoDB erstellt werden. Außerdem wird kurz beschrieben, wie die E-Mail-Adresse eines Benutzers in MongoDB eindeutig wird.

Das Inhaltsverzeichnis dieses Artikels lautet wie folgt:

  1. Eindeutige Indizes in MongoDB
  2. Erstellen Sie einen eindeutigen Index in MongoDB
  3. Verhalten eindeutiger Indizes in MongoDB
  4. Validieren Sie eindeutige E-Mails mit Mongoose

Eindeutiger Index in MongoDB

Ein eindeutiger Index garantiert, dass die indizierten Felder keine doppelten Werte enthalten, wodurch sichergestellt wird, dass die indizierten Felder eindeutig sind. Während der Erstellung einer Sammlung erstellt MongoDB standardmäßig einen eindeutigen Index für die Spalte _id.

Verwenden Sie den Befehl db.collection.createIndex(), um einen eindeutigen Index zu generieren, wobei die Option unique auf true gesetzt ist.

db.collection.createIndex( <key and index type specification>, { unique: true } )

Eindeutiger Index für ein einzelnes Feld

Verwenden Sie das folgende Verfahren in mongosh, um einen eindeutigen Index für das Feld user_id der Sammlung members zu erstellen.

db.members.createIndex( { "user_id": 1 }, { unique: true } )

Eindeutiger zusammengesetzter Index

Bei zusammengesetzten Indizes können Sie auch eine eindeutige Einschränkung festlegen. Beispielsweise erzwingt MongoDB die Eindeutigkeit beim Kombinieren von Indexschlüsselwerten, wenn Sie die Eindeutigkeitsbeschränkung für einen zusammengesetzten Index verwenden.

Verwenden Sie die folgende Operation in mongosh, um einen eindeutigen Index für die Felder groupNumber, lastname und firstname der Sammlung members zu erstellen.

db.members.createIndex( { groupNumber: 2, lastname: 1, firstname: 1 }, { unique: true } )

Der Index stellt sicher, dass jede Kombination der Werte groupNumber, lastname und firstname eindeutig ist.

Betrachten Sie die folgende Sammlung mit dem folgenden Dokument.

{ _id: 1, a: [ { loc: "A", qty: 5 }, { qty: 10 } ] }

Erstellen Sie einen eindeutigen zusammengesetzten Multikey-Index für a.loc und a.qty.

db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )

Die folgenden Dokumente können in die Sammlung aufgenommen werden, da der Index die Eindeutigkeit für die Kombination der Werte a.loc und a.qty garantiert.

db.collection.insertMany( [
   { _id: 2, a: [ { loc: "A" }, { qty: 6 } ] },
   { _id: 3, a: [ { loc: "A", qty: 12 } ] }
] )

Verhalten des eindeutigen Index in MongoDB

Einschränkungen:

Wenn die Sammlung bereits Daten enthält, die gegen die Eindeutigkeitsanforderung des Index verstoßen würden, kann MongoDB keinen eindeutigen Index für die bereitgestellten Indexfelder erstellen. Bei einem Hash-Index können Sie keine Eindeutigkeitsbeschränkung definieren.

Verwenden Sie Replikatsätze und Sharded-Cluster, um einen eindeutigen Index zu erstellen

Die Verwendung eines fortlaufenden Vorgangs zum Erstellen eines eindeutigen Indexes für Replikatsätze und fragmentierte Cluster erfordert das Stoppen aller Schreibvorgänge in die Sammlung während des gesamten Verfahrens.

Verwenden Sie den fortlaufenden Vorgang nicht, wenn Sie während des Vorgangs nicht alle Schreibvorgänge in die Sammlung stoppen können. Erstellen Sie stattdessen einen einzigartigen Index für die Sammlung, indem Sie Folgendes ausgeben:

  1. db.collection.createIndex() auf dem primären für einen Replikatsatz
  2. db.collection.createIndex() auf mongos für einen Sharded-Cluster

Unique Constraint über separate Dokumente hinweg

Die Eindeutigkeitsanforderung gilt für jedes Dokument in der Sammlung. Der eindeutige Index verhindert, dass der indizierte Schlüssel in verschiedenen Dokumenten denselben Wert hat.

Da die Einschränkung nur für separate Dokumente gilt, kann ein Dokument ein Array von Elementen enthalten, die zu sich wiederholenden Indexschlüsselwerten für einen eindeutigen Multikey-Index führen, solange die Indexschlüsselwerte für das Dokument nicht mit denen für ein anderes Dokument dupliziert werden. Der wiederholte Indexeintrag wird in diesem Szenario nur einmal in den Index eingetragen.

Zum Beispiel eine Sammlung, die die folgenden Dokumente enthält.

{ _id: 1, a: [ { loc: "A", qty: 6 }, { qty: 10 } ] }
{ _id: 2, a: [ { loc: "A" }, { qty: 7 } ] }
{ _id: 3, a: [ { loc: "A", qty: 12 } ] }

Erstellen Sie einen eindeutigen zusammengesetzten Multikey-Index für a.loc und a.qty.

db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )

Wenn kein anderes Dokument in dieser Sammlung einen Indexschlüsselwert von {"a.loc": "B", "a.qty": null} hat, ermöglicht der eindeutige Index, dass das folgende Dokument in die Sammlung eingefügt wird.

db.collection.insertOne( { _id: 4, a: [ { loc: "B" }, { loc: "B" } ] } )

Eindeutiger Index und fehlendes Feld

Wenn ein Dokument in einem eindeutigen Index keinen Wert für das indizierte Feld enthält, speichert der Index einen Nullwert für dieses Dokument. MongoDB lässt aufgrund der Eindeutigkeitsbeschränkung zu, dass nur bei einem Dokument die indizierte Spalte fehlt.

Die Indexerstellung schlägt mit einem doppelten Schlüsselfehler fehl, wenn es mehr als ein Dokument ohne Wert für das indizierte Feld gibt oder wenn das indizierte Feld fehlt.

Eine Sammlung hat zum Beispiel einen eindeutigen Index auf x.

db.collection.createIndex( { "x": 13 }, { unique: true } )

Wenn die Sammlung nicht bereits ein Dokument enthält, dem das Feld x fehlt, ermöglicht der eindeutige Index das Einfügen eines Dokuments ohne das Feld x.

db.collection.insertOne( { y: 2 } )

Wenn die Sammlung jedoch bereits ein Dokument ohne Feld x enthält, schlägt der eindeutige Index beim Einfügen eines Dokuments ohne Feld x fehl.

db.collection.insertOne( { z: 2 } )

Die Operation kann das Dokument aufgrund eines Verstoßes gegen die Eindeutigkeitsbeschränkung für den Wert des Felds x nicht einfügen.

WriteResult({
   "nInserted" : 0,
   "writeError" : {
      "code" : 12000,
      "errmsg" : "E12000 duplicate key error index: test.collection.$a.b_1 dup key: { : null }"
   }
})

Eindeutiger Teilindex

Nur die Dokumente in einer Sammlung, die einem bestimmten Filterausdruck entsprechen, werden in Teilindizes indiziert. Wenn Sie also sowohl einen partialFilterExpression als auch einen Unique-Constraint verwenden, gilt der Unique-Constraint nur für Dokumente, die mit dem Filterausdruck übereinstimmen.

Wenn die Dokumente die Filteranforderungen nicht erfüllen, verhindert ein Teilindex mit Eindeutigkeitsbeschränkung nicht das Einfügen von Dokumenten, die die Eindeutigkeitsbeschränkung nicht erfüllen.

Sharded Cluster und Unique Index

Bei einem Hash-Index können Sie keine Eindeutigkeitsbeschränkung definieren.

Nur die folgenden Indizes können in einer Ranged-Sharding-Sammlung eindeutig sein.

  1. Der Indexwert des Shard-Schlüssels.
  2. Ein zusammengesetzter Index mit einem Präfix als Shard-Schlüssel.
  3. Der Standardindex _id; Der _id-Index erzwingt jedoch nur dann die Eindeutigkeitsanforderung pro Shard, wenn die _id-Felder nicht der Shard-Schlüssel oder das Shard-Schlüssel-Präfix sind.

Die eindeutigen Indexeinschränkungen bedeuten Folgendes:

  1. Sie können die Sammlung nicht teilen, wenn die Sammlung andere eindeutige Indizes für eine zu teilende Sammlung hat.
  2. Sie können keine eindeutigen Indizes für eine bereits fragmentierte Sammlung für andere Felder erstellen.

Sparse- und Non-Sparse-Unique-Index

Ab MongoDB 5.0 kann eine einzelne Sammlung eindeutige Sparse- und Non-Sparse-Indizes mit demselben Schlüsselmuster haben.

Eindeutige und spärliche Indexerstellung

In diesem Beispiel werden mehrere Indizes mit demselben Schlüsselmuster und unterschiedlichen sparse-Auswahlmöglichkeiten erstellt.

db.scores.createIndex( { score : 2 }, { name: "unique_index", unique: true } )
db.scores.createIndex( { score : 2 }, { name: "unique_sparse_index", unique: true, sparse: true } )

Grund- und Sparse-Index-Erstellung

Mit und ohne Option sparse können Sie einfache Indizes mit demselben Schlüsselmuster aufbauen.

db.scores.createIndex( { score : 2 }, { name: "sparse_index", sparse: true } )
db.scores.createIndex( { score : 2 }, { name: "basic_index" } )

Doppelte Schlüsselmuster in Basis- und eindeutigen Indizes

Mit MongoDB 5.0 haben Sie möglicherweise grundlegende und eindeutige Indizes mit demselben Schlüsselmuster. Aufgrund der Duplizierung von Schlüsselmustern ist es möglich, bereits indizierten Feldern einen eindeutigen Index hinzuzufügen.

Beispiel:

Erstellen Sie einen Basisindex mit dem Schlüsselmuster { score: 2 } und fügen Sie drei Dokumente ein.

db.scores.createIndex( { score : 1 }, { name: "basic_index" } )
db.scores.insert( { score : 1 } )
db.scores.insert( { score : 2 } )
db.scores.insert( { score : 4 } )

Erstellen Sie einen eindeutigen Index mit demselben Schlüsselmuster { score: 2 }.

db.scores.createIndex( { score : 2 }, { name: "unique_index", unique: true } )

Der Versuch, ein doppeltes score-Dokument einzufügen, schlägt aufgrund des eindeutigen Index fehl.

db.scores.insert( { score : 4 } )

Validieren Sie eindeutige E-Mails mit Mongoose

Mit Mongoose können Sie Duplikate in Ihren Datenbanken durch Validierung verhindern. Die Validierung ist im Typ Schema definiert und ist eine Middleware.

Sie können Ihre Validierung auch im Schema erstellen oder die integrierte Validierung von Mongooses verwenden. Um Duplikate zu vermeiden, empfehlen wir die Verwendung der Eigenschaft unique, da sie Mongoose mitteilt, dass jedes Dokument einen eindeutigen Wert für den angegebenen Pfad haben sollte.

Es ist eine Abkürzung für die Erstellung eines eindeutigen MongoDB-Index für, in diesem Fall, email.

Wenn Sie darauf warten, dass der Index erstellt wird, können Sie Mongooses Promise-basiertes Ereignis Model.init() verwenden, wie unten gezeigt.

const User = mongoose.model('User', mongoose.Schema({
  email: {type: String, required: true, match: /.+\@.+\..+/, unique: true}
}));
await User.create([
  {email: 'gmail@google.com'}, {email: 'bill@microsoft.com'},
  {email: 'test@gmail.com'}
]);

await User.init();
try {
  await User.create({email: 'gmail@google.com'});
} catch (error) {
  error.message;  // 'E12000 duplicate key error...'
}

In diesem Artikel werden eindeutige Indizes in MongoDB ausführlich besprochen. Darüber hinaus erfolgt die Validierung eindeutiger E-Mails am Ende in mongoose von MongoDB.

Verwandter Artikel - MongoDB Index