Próbuję pozwolić MongoDB wykryć zduplikowaną wartość na podstawie jej indeksu. Myślę, że jest to możliwe w MongoDB, ale przez opakowanie Mongoose wydaje się, że wszystko jest zepsute. Więc dla czegoś takiego:
User = new Schema ({
email: {type: String, index: {unique: true, dropDups: true}}
})
Za pomocą tego samego adresu e-mail mogę zapisać 2 użytkowników. Cerować.
Ten sam problem został wyrażony tutaj: https://github.com/LearnBoost/mongoose/issues/56 , ale ten wątek jest stary i prowadzi donikąd.
Na razie ręcznie dzwonię do bazy danych, aby znaleźć użytkownika. To połączenie nie jest drogie, ponieważ „e-mail” jest indeksowany. Ale nadal byłoby miło pozwolić sobie na to natywnie.
Czy ktoś ma na to rozwiązanie?
Odpowiedzi:
Ups! Musisz tylko zrestartować mongo.
źródło
I ponownie zindeksuj, używając:
W testowaniu, ponieważ nie mam ważnych danych, możesz również:
źródło
Napotkałem ten sam problem: dodałem unikalne ograniczenie dla tego
email
pola do naszegoUserSchema
po dodaniu użytkowników do bazy danych i nadal byłem w stanie zapisywać użytkowników za pomocą podwójnych e-maili. Rozwiązałem to, wykonując następujące czynności:1) Usuń wszystkie dokumenty z kolekcji użytkowników.
2) Z powłoki mongo wykonaj polecenie:
db.users.createIndex({email: 1}, {unique: true})
Jeśli chodzi o krok 1, zwróć uwagę, że z dokumentów Mongo:
https://docs.mongodb.com/manual/core/index-unique/
źródło
Takie zachowanie występuje również, jeśli zostawiłeś kilka duplikatów w Mongo. Mongoose spróbuje utworzyć je w Mongo podczas uruchamiania aplikacji.
Aby temu zapobiec, możesz obsłużyć ten błąd w następujący sposób:
yourModel.on('index', function(err) { if (err?) { console.error err } );
źródło
Ok, udało mi się rozwiązać ten problem z mongoshell, dodając indeks na polu i ustawiając unikalną właściwość:
db.<collectionName>.ensureIndex({fieldName: 1}, {unique: true});
Shell powinien zareagować w ten sposób:
{ "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }
Teraz, aby szybko przetestować z mongoshell:
var doc = {fieldName: 'abc'}; db.<collectionName>.insert(doc)
Powinien dać: WriteResult ({"nInserted": 1})
Ale powtarzając ponownie:
Da:
WriteResult({ "nInserted" : 0, "writeError" : { "code" : 11000, "errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: fuelConsumption.users.$email_1 dup key: { : \"[email protected]\" }" } })
źródło
Zrobiłem coś takiego:
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
Dodałem
Foo.createIndexes()
wiersz bc Otrzymałem następujące ostrzeżenie o wycofaniu, gdy kod był uruchamiany:(node:21553) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.
Nie jestem pewien, czy
Foo.createIndexes()
jest asynchroniczny, ale wydaje się, że rzeczy AFAIK działają dobrzeźródło
index: true
że mój unikalny indeks został utworzony.Zgodnie z dokumentacją: https://docs.mongodb.com/v2.6/tutorial/modify-an-index/
NIE URUCHAMIAJ PONOWNIE MONGO!
1 - upuść kolekcję
2 - ponownie zindeksuj tabelę
db.users.ensureIndex({email: 1, type: 1}, {unique: true})
źródło
Mongoose jest trochę luźny podczas wymuszania unikalnych indeksów z poziomu aplikacji; Dlatego preferowane jest wymuszanie unikalnych indeksów z samej bazy danych za pomocą mongo cli lub jawne poinformowanie mongoose, że poważnie podchodzisz do
unique
indeksu, pisząc następujący wiersz kodu tuż po UserSchema:UserSchema.index({ username: 1, email: 1 }, { unique: true});
Będzie to egzekwować unikalny indeks na obu
username
iemail
pól w UserSchema. Twoje zdrowie.źródło
Mongoose po cichu nie doda unikalnego indeksu, gdy:
W pierwszym przypadku wypisz indeksy za pomocą
db.collection.getIndexes()
i usuń stary indeks za pomocądb.collection.dropIndex("index_name")
. Po ponownym uruchomieniu aplikacji Mongoose powinna ona poprawnie dodać nowy indeks.W drugim przypadku musisz usunąć duplikaty przed ponownym uruchomieniem aplikacji Mongoose.
źródło
walidator unikatowy-mangusty
Jak korzystać z tej wtyczki:
1) npm install --save mongoose-unique-validator
2) w swoim schemacie postępuj zgodnie z tym przewodnikiem:
// 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) metody mangusty
Podczas korzystania z metod takich jak
findOneAndUpdate
będziesz musiał przekazać ten obiekt konfiguracyjny:{ runValidators: true, context: 'query' }
ie. User.findOneAndUpdate( { email: '[email protected]' }, { email: '[email protected]' }, { runValidators: true, context: 'query' }, function(err) { // ... }
4) opcje dodatkowe
bez rozróżniania wielkości liter
użyj opcji uniqueCaseInsensitive w swoim schemacie
ie. email: { type: String, index: true, unique: true, required: true, uniqueCaseInsensitive: true }
niestandardowe komunikaty o błędach
ie. exampleSchema.plugin(uniqueValidator, { message: 'Error, expected {PATH} to be unique.' });
Teraz możesz dodawać / usuwać unikalną właściwość do swoich schematów bez martwienia się o ponowne uruchamianie mongo, usuwanie baz danych lub tworzenie indeksów.
Ostrzeżenia (z dokumentacji):
Ponieważ polegamy na operacjach asynchronicznych w celu sprawdzenia, czy dokument istnieje w bazie danych, możliwe jest wykonanie dwóch zapytań w tym samym czasie, oba zwracają 0, a następnie oba wstawiają do MongoDB.
Poza automatycznym blokowaniem kolekcji lub wymuszaniem pojedynczego połączenia nie ma prawdziwego rozwiązania.
Dla większości naszych użytkowników nie będzie to problemem, ale należy być tego świadomym.
źródło
Najnowsza odpowiedź: w ogóle nie ma potrzeby restartowania mongodb, jeśli colleciton ma już indeksy o tej samej nazwie, mongoose nie odtworzy ponownie twoich indeksów, więc najpierw upuść istniejące indeksy colleciton, a teraz, gdy uruchomisz mongoose, utworzy nowy indeks , powyższy proces rozwiązał mój problem.
źródło
Możesz również rozwiązać ten problem, upuszczając indeks;
załóżmy, że chcesz usunąć unikalny indeks z kolekcji
users
i polausername
, wpisz to:db.users.dropIndex('username_1');
źródło
Jeśli tabela / kolekcja jest pusta, utwórz unikalny indeks dla pola:
db.<collection_name>.createIndex({'field':1}, {unique: true})
Jeśli tabela / kolekcja nie jest pusta, usuń kolekcję i utwórz indeks:
db.<collection_name>.drop() db.<collection_name>.createIndex({'field':1}, {unique: true})
Teraz zrestartuj mongoDB.
źródło
sprawdź, czy autoIndex w schemacie ma wartość true, może ustawić false (domyślnie true), gdy używasz opcji mongoose.connect
źródło
Przez jakiś czas miałem do czynienia z tym samym problemem i dużo szukałem, a rozwiązaniem dla mnie była
createIndexes()
funkcja.Chciałbym, żeby to pomogło.
więc kod będzie taki.
User = new Schema ({ email: {type: String, unique: true} }); User.createIndexes();
źródło
Jeśli używasz opcji
autoIndex: false
w metodzie połączenia takiej jak ta:mongoose.connect(CONNECTION_STRING, { autoIndex: false });
Spróbuj to usunąć. Jeśli to nie zadziała, spróbuj ponownie uruchomić mongodb, jak wiele sugeruje w tym wątku.
źródło
Możesz zdefiniować swój schemat jako
User = new Schema ({ email: { type: String, unique: true } })
Ale może to nie zadziała, gdy istnieje już dokument, a potem zmieniłeś schemat użytkownika. Możesz utworzyć indeks wiadomości e-mail dla tej kolekcji użytkowników, jeśli nie chcesz porzucać tej kolekcji. Za pomocą tego polecenia możesz utworzyć indeks wiadomości e-mail.
db.User.createIndex({email:1},{unique: true})
Możesz też po prostu upuścić kolekcję i ponownie dodać użytkownika.
Aby upuścić kolekcję, możesz wprowadzić to:
źródło
Kiedy napotkałem ten problem, próbowałem wiele razy porzucić bazę danych, ponownie uruchomić serwer (nodemon) i żadna ze sztuczek w ogóle nie działała. Znalazłem następujące obejście, dzięki Robo 3T:
_id_
jako domyślny. Teraz wybierz Dodaj indeksemail
, na przykład pole e-mailPodaj klucze jako JSON. Na przykład
{ "email": 1 }
Kliknij pole wyboru Unikalne
Dzięki temu w MongoDB nie zostaną zapisane żadne zduplikowane wiadomości e-mail.
źródło
Upewnij się, że Twoja kolekcja nie zawiera dodatkowego pola, w którym właśnie umieściłeś unikalny indeks.
Następnie po prostu uruchom ponownie aplikację (mangusta). Po prostu dyskretnie dodaje indeks nie działa.
źródło
Usuwanie wszystkich dokumentów z kolekcji:
I restart, jak wspominali inni, działał dla mnie
źródło
Jeśli Twoja baza danych MongoDB działa jako usługa (łatwy sposób na znalezienie tego polega na tym, że nie musisz łączyć się z bazą danych bez uruchamiania pliku mongod.exe przez terminal), to po wprowadzeniu zmian może być konieczne ponowne uruchomienie usługi i / lub całkowicie usuń bazę danych.
Jest to dość dziwne, ponieważ dla niektórych użytkowników po prostu upuszczenie jednej kolekcji zadziałało. Niektórzy z nich musieli po prostu usunąć bazę danych. Ale to nie zadziałało dla mnie. Porzuciłem bazę danych, a następnie ponownie uruchomiłem usługę MongoDB Server.
Aby ponownie uruchomić wyszukiwanie usług Usługi na pasku wyszukiwania systemu Windows, a następnie znajdź usługę MongoDB, kliknij dwukrotnie, aby ją otworzyć, a następnie zatrzymaj i uruchom ponownie usługę.
Jeśli inne metody nie zadziałały, wierzę, że to zadziała.
źródło
W moim przypadku mangusta była przestarzała. Sprawdziłem to, uruchamiając npm przestarzały na CMD. i zaktualizował „mangusta”.
Powiedz, czy to też zadziałało.
źródło
Po połączeniu bazy danych z aplikacją dodaj opcję: "audoIndex: true" na przykład w moim kodzie zrobiłem tak:
const options = { // your options go here ... // this code is the solution audoIndex: true } mongoose.connect(DB_URI, options);
Upuściłem też kolekcję, z którą mam problem i odtworzyłem ją, aby mieć pewność, że zadziała. Znalazłem to rozwiązanie pod adresem : https://dev.to/emmysteven/solved-mongoose-unique-index-not-working-45d5. Próbowałem również rozwiązań typu „restart MongoDB”, ale nie działały.
źródło