mongoDB / mongoose: einzigartig, wenn nicht null

Ich habe mich gefragt, ob es eine Möglichkeit gibt, einen eindeutigen Auflistungseintrag zu erzwingen, aber nur, wenn der Eintrag nicht null ist . e Beispielschema:

var UsersSchema = new Schema({ name : {type: String, trim: true, index: true, required: true}, email : {type: String, trim: true, index: true, unique: true} }); 

“E-Mail” ist in diesem Fall nicht erforderlich, aber wenn “E-Mail” gespeichert wird, möchte ich sicherstellen, dass dieser Eintrag eindeutig ist (auf databaseebene).

Leere Einträge scheinen den Wert ‘null’ zu erhalten, so dass jeder Eintrag ohne E-Mail mit der Option ‘unique’ abstürzt (wenn es einen anderen Benutzer ohne E-Mail gibt).

Im Moment löse ich es auf einer Anwendungsebene, würde aber gerne diese DB-Abfrage speichern.

Danke

Ab MongoDB v1.8 + können Sie das gewünschte Verhalten erzielen, indem Sie eindeutige Werte sicherstellen, aber mehrere Dokumente ohne das Feld zulassen, indem Sie die sparse Option beim Definieren des Index auf true setzen. Wie in:

 email : {type: String, trim: true, index: true, unique: true, sparse: true} 

Oder in der shell:

 db.users.ensureIndex({email: 1}, {unique: true, sparse: true}); 

Beachten Sie, dass ein eindeutiger, spärlicher Index weiterhin nicht mehrere Dokumente mit einem email Feld mit einem Wert von null erlaubt, sondern nur mehrere Dokumente ohne ein email Feld.

Siehe http://docs.mongodb.org/manual/core/index-sparse/

tl; dr

Ja, es kann gemacht werden.
Mehrere Dokumente, bei denen das Feld auf null oder nicht definiert ist, während eindeutige “tatsächliche” Werte durchgesetzt werden.

Anforderungen :

  • MongoDB v3.2 +.
  • Wenn Ihr Feld einen tatsächlichen Wert hat, sollte es einen bestimmten Typ haben (z. B. immer eine Zeichenkette).

Wie? Rufen Sie die Implementierungsdetails unten auf.

längere Version

Um Nolans Antwort zu ergänzen, können Sie beginnend mit MongoDB v3.2 einen teilweise eindeutigen Index mit einem Filterausdruck verwenden.

Der partielle Filterausdruck hat Einschränkungen. Es kann nur Folgendes enthalten:

  • Gleichheitsausdrücke (dh Feld: Wert oder Verwendung des $eq Operators),
  • $exists: true Ausdruck,
  • $gt , $gte , $lt , $lte Ausdrücke,
  • $type Ausdrücke,
  • $and operator nur auf oberster Ebene

Dies bedeutet, dass der triviale Ausdruck {"yourField"{$ne: null}} nicht verwendet werden kann.

Unter der Annahme, dass in Ihrem Feld immer derselbe Typ verwendet wird , können Sie einen $type Ausdruck verwenden .

 { field: { $type:  |  } } 

Implementierung

Mungo

Sie können es in einem Mungo-Schema angeben:

 const UsersSchema = new Schema({ name: {type: String, trim: true, index: true, required: true}, email: { type: String, trim: true, index: { unique: true, partialFilterExpression: {email: {$type: 'string'}} } } }); 

oder fügen Sie sie direkt der Sammlung hinzu (die den nativen node.js-Treiber verwendet):

 User.collection.createIndex("email", { unique: true, partialFilterExpression: { "email": { $type: "string" } } }); 

nativer Mongodb-Treiber

mit collection.createIndex

 db.collection('users').createIndex({ "email": 1 }, { unique: true, partialFilterExpression: { "email": { $type: "string" } } }, function (err, results) { // ... } ); 

Mongodb-Muschel

Verwenden von db.collection.createIndex :

 db.users.createIndex({ "email": 1 }, { unique: true, partialFilterExpression: { "email": {$type: "string"} } }) 

Dies ermöglicht das Einfügen mehrerer Datensätze mit einer null E-Mail oder ohne ein E-Mail-Feld, aber nicht mit der gleichen E-Mail-Zeichenfolge.

Nur ein kurzes Update für diejenigen, die dieses Thema erforschen.

Die ausgewählte Antwort funktioniert, aber Sie sollten stattdessen die Verwendung von Teilindizes in Betracht ziehen.

Geändert in Version 3.2: MongoDB bietet ab MongoDB 3.2 die Möglichkeit, Teilindizes anzulegen. Teilindizes bieten eine Obermenge der functionalität von Sparse-Indizes. Wenn Sie MongoDB 3.2 oder höher verwenden, sollten partielle Indizes gegenüber spärlichen Indizes bevorzugt werden.

Mehr Doco auf Teilindizes: https://docs.mongodb.com/manual/core/index-partial/

Tatsächlich wird nur das erste Dokument, bei dem “E-Mail” als Feld nicht existiert, erfolgreich gespeichert. Nachfolgende Speicherungen, bei denen “E-Mail” nicht vorhanden ist, schlagen fehl, wenn ein Fehler angezeigt wird (siehe Code-Schnipsel unten). Sehen Sie sich die offizielle MongoDB-Dokumentation in Bezug auf Unique Indexes und Missing Keys unter http://www.mongodb.org/display/DOCS/Indexes#Indexes-UniqueIndexes an .

  // NOTE: Code to executed in mongo console. db.things.ensureIndex({firstname: 1}, {unique: true}); db.things.save({lastname: "Smith"}); // Next operation will fail because of the unique index on firstname. db.things.save({lastname: "Jones"}); 

Per Definition kann der eindeutige Index nur einen Wert nur einmal speichern lassen. Wenn Sie null als einen solchen Wert betrachten, kann er nur einmal eingefügt werden! Sie sind in Ihrem Ansatz korrekt, indem Sie ihn auf Anwendungsebene sicherstellen und validieren. So kann es gemacht werden.

Sie können auch diese http://www.mongodb.org/display/DOCS/Querying+and+nulls lesen