Zastanawiałem się, czy istnieje sposób na wymuszenie unikalnego wpisu kolekcji, ale tylko wtedy, gdy wpis nie jest pusty . e Przykładowy schemat:
var UsersSchema = new Schema({
name : {type: String, trim: true, index: true, required: true},
email : {type: String, trim: true, index: true, unique: true}
});
„e-mail” w tym przypadku nie jest wymagany, ale jeśli „e-mail” jest zapisany, chcę się upewnić, że ten wpis jest unikalny (na poziomie bazy danych).
Puste wpisy wydają się mieć wartość „null”, więc każdy wpis bez wiadomości e-mail ulega awarii z opcją „unikalny” (jeśli jest inny użytkownik bez adresu e-mail).
Obecnie rozwiązuję to na poziomie aplikacji, ale chciałbym zapisać to zapytanie db.
dzięki
email
pola, a nie tam, gdzie w rzeczywistości ono ma wartośćnull
. Zobacz zaktualizowaną odpowiedź.tl; dr
Tak, możliwe jest posiadanie wielu dokumentów z polem ustawionym
null
lub niezdefiniowanym, przy wymuszaniu unikalnych „rzeczywistych” wartości.wymagania :
string
lubobject
kiedy nienull
).Jeśli nie interesują Cię szczegóły, możesz przejść do
implementation
sekcji.dłuższa wersja
Aby uzupełnić odpowiedź @ Nolana, zaczynając od MongoDB v3.2, możesz użyć częściowego unikatowego indeksu z wyrażeniem filtru.
Wyrażenie filtra częściowego ma ograniczenia. Może zawierać tylko:
Oznacza to, że
{"yourField"{$ne: null}}
nie można użyć trywialnego wyrażenia .Jednak zakładając, że Twoje pole zawsze używa tego samego typu , możesz użyć
$type
wyrażenia .W MongoDB v3.6 dodano obsługę określania wielu możliwych typów, które mogą być przekazywane jako tablica:
co oznacza, że pozwala, aby wartość była dowolnego z wielu typów, gdy nie
null
.Dlatego, jeśli chcemy, aby
email
pole w poniższym przykładzie akceptowało jednąstring
lub, powiedzmy,binary data
wartości, odpowiednim$type
wyrażeniem byłoby:realizacja
mangusta
Możesz to określić w schemacie mangusty:
lub bezpośrednio dodaj go do kolekcji (która używa natywnego sterownika node.js):
natywny sterownik mongodb
za pomocą
collection.createIndex
mongodb shell
używając
db.collection.createIndex
:Umożliwi to wstawianie wielu rekordów z
null
wiadomością e-mail lub bez pola adresu e-mail, ale nie z tym samym ciągiem wiadomości e-mail.źródło
unique
isparse
). Zaktualizowałem schemat za pomocą tej odpowiedzi, porzuciłem istniejący indeks i zadziałało to jak marzenie.Krótka informacja dla osób badających ten temat.
Wybrana odpowiedź będzie działać, ale możesz zamiast tego rozważyć użycie indeksów częściowych.
Więcej dokumentacji na temat indeksów częściowych: https://docs.mongodb.com/manual/core/index-partial/
źródło
W rzeczywistości tylko pierwszy dokument, w którym pole „e-mail” nie istnieje, zostanie pomyślnie zapisany. Kolejne zapisy, w których nie ma „e-maila”, zakończą się niepowodzeniem i wyświetlą błąd (patrz fragment kodu poniżej). Dlatego zajrzyj do oficjalnej dokumentacji MongoDB w odniesieniu do unikalnych indeksów i brakujących kluczy tutaj pod adresem http://www.mongodb.org/display/DOCS/Indexes#Indexes-UniqueIndexes .
Z definicji unikalny indeks może zezwalać na przechowywanie tylko jednej wartości tylko raz. Jeśli uznasz null za jedną z takich wartości, można ją wstawić tylko raz! Masz rację w swoim podejściu, zapewniając i weryfikując je na poziomie aplikacji. Tak można to zrobić.
Możesz również przeczytać ten http://www.mongodb.org/display/DOCS/Querying+and+nulls
źródło