E11000 duplikat indeksu błędów klucza w mongob mongodb

228

Poniżej znajduje się mój userschemat w user.jsmodelu -

var userSchema = new mongoose.Schema({
    local: {
        name: { type: String },
        email : { type: String, require: true, unique: true },
        password: { type: String, require:true },
    },
    facebook: {
        id           : { type: String },
        token        : { type: String },
        email        : { type: String },
        name         : { type: String }
    }
});

var User = mongoose.model('User',userSchema);

module.exports = User;

Tak używam go w moim kontrolerze -

var user = require('./../models/user.js');

Tak zapisuję to w db -

user({'local.email' : req.body.email, 'local.password' : req.body.password}).save(function(err, result){
    if(err)
        res.send(err);
    else {
        console.log(result);
        req.session.user = result;
        res.send({"code":200,"message":"Record inserted successfully"});
    }
});

Błąd -

{"name":"MongoError","code":11000,"err":"insertDocument :: caused by :: 11000 E11000 duplicate key error index: mydb.users.$email_1  dup key: { : null }"} 

Sprawdziłem kolekcję db i nie ma takiego zduplikowanego wpisu, czy mogę powiedzieć, co robię źle?

FYI - req.body.emaili req.body.passwordpobieram wartości.

Sprawdziłem również ten post, ale nie pomogłem STACK LINK

Jeśli usunąłem całkowicie, wstawia dokument, w przeciwnym razie zgłasza błąd „Duplikuj” błąd, nawet jeśli mam wpis w local.email

Trialcoder
źródło
1
Miał ten sam błąd! Podczas programowania wyłączyliśmy automatyczne indeksowanie i używaliśmy małych nazw / kluczy schematów. Później zdecydowaliśmy się zamiast tego użyć TitleCase, ale nie udało nam się zaktualizować nazw indeksów (tj.: TitleCase zamiast TitleCase). Więc kiedy włączyliśmy indeksowanie, otrzymaliśmy ten błąd. Zajęło to trochę czasu, aby to zrozumieć. Będziesz chciał upewnić się, że wszystkie nazwy / klucze są nazywane dokładnie wszędzie.
Jeach
6
Miałem ten sam błąd i ustawienie mangusty unique: falsenie miało żadnego wpływu. Uświadomiłem sobie, że najpierw muszę upuścić stół, a potem zadziała. Możesz zrobić coś takiego db.whateverthecollection.drop({}). Uważaj, usuwa kolekcję.
Pere
1
_id: mongoose.Types.ObjectId dodaj, ponieważ wymagany jest unikalny identyfikator
Mayank Pandav

Odpowiedzi:

239

Komunikat o błędzie mówi, że istnieje już rekord z nulladresem e-mail. Innymi słowy, masz już użytkownika bez adresu e-mail.

Odpowiednia dokumentacja do tego:

Jeśli dokument nie ma wartości pola indeksowanego w unikalnym indeksie, indeks zapisze dla tego dokumentu wartość zerową. Ze względu na wyjątkowe ograniczenie MongoDB zezwoli tylko na jeden dokument bez pola indeksowanego. Jeśli istnieje więcej niż jeden dokument bez wartości dla pola indeksowanego lub brakuje pola indeksowanego, kompilacja indeksu zakończy się niepowodzeniem z błędem duplikatu klucza.

Możesz połączyć unikalne ograniczenie z rzadkim indeksem, aby odfiltrować te wartości zerowe z unikalnego indeksu i uniknąć błędu.

unikalne indeksy

Rzadkie indeksy zawierają tylko wpisy dla dokumentów, które mają pole indeksowane, nawet jeśli pole indeksu zawiera wartość null.

Innymi słowy, indeks rzadki jest odpowiedni dla wielu dokumentów null wartości.

rzadkie indeksy


Z komentarzy:

Twój błąd mówi, że klucz został nazwany, mydb.users.$email_1co sprawia, że ​​podejrzewam, że masz indeks na jedno users.emaili drugie users.local.email(ten pierwszy jest w tej chwili stary i nieużywany). Usunięcie pola z modelu Mongoose nie wpływa na bazę danych. Sprawdź, mydb.users.getIndexes()czy tak jest, i ręcznie usuń niechciany indeks za pomocą mydb.users.dropIndex(<name>).

RickN
źródło
1
Właśnie usunąłem ten zerowy dokument i zadziałało :) +1 .. dzięki za pomoc
Trialcoder
70
Twój błąd mówi, że klucz został nazwany, mydb.users.$email_1co sprawia, że ​​podejrzewam, że masz indeks na jedno users.emaili drugie users.local.email(ten pierwszy jest w tej chwili stary i nieużywany). Usunięcie pola z modelu Mongoose nie wpływa na bazę danych. Sprawdź, mydb.users.getIndexes()czy tak jest, i ręcznie usuń niechciany indeks za pomocą mydb.users.dropIndex(<name>).
RickN
17
Lub użyj, db.users.dropIndexes()jeśli dokonujesz wielu zmian indeksu
cs_stackX
1
Był to dla mnie problem, gdy korzystałem z wtyczki mongoose passport-local-mongoose bez ustawiania nazwy użytkownika dla nowych użytkowników.
pokaż
1
To kwestia, perspektywa, a może nawet opinia, @titoih - czy wartość jest zerowa, czy brak wartości jest wartością taką jak każda inna, czy też jest przypadkiem szczególnym? „a @ bc” i „a @ bc” są takie same, czy „nic” i „nic” są również takie same? W przypadku indeksu niesparse odpowiedź w MongoDB brzmi „tak”. Inne bazy danych (takie jak MySQL) powiedziały „nie”.
RickN
64

Jeśli nadal jesteś w środowisku programistycznym, upuściłbym całą bazę danych i zacząłbym od nowa z nowym schematem.

Z linii poleceń

 mongo
use dbName;
db.dropDatabase();
exit
Stóg
źródło
46
Myślę, że to rozwiązanie jest bardzo agresywne, myślę, że wystarczy, db.collection.dropIndexes()jak powiedział
cs_stackX
2
@JorgeGarza Miałem ten sam problem. Właśnie upuściłem kolekcję i potem wszystko zaczęło działać dobrze.
Sandip Subedi
Przypadkowo zainicjowałem kolekcję unikalnym identyfikatorem dwóch moich pól. Później, kiedy chciałem dodać wiele dokumentów o tym samym identyfikatorze. Nie pozwoliłoby mi to, dopóki nie usunę kolekcji i nie otworzę jej ponownie.
Meir Snyder
1
Jeśli jesteś nowy w rozwoju, jest to dobra okazja, aby poeksperymentować i dowiedzieć się, jak rozwiązać ten problem ... zamiast
napotykać
Komentarz @JorgeGarza ma sens. Porzucone indeksy zostaną ponownie odbudowane przez plik schematu po zrestartowaniu serwera. Również działało.
retr0
26

Sprawdź indeksy kolekcji.

Miałem ten problem z powodu przestarzałych indeksów w kolekcji dla pól, które powinny być przechowywane inną ścieżką.

Mongoose dodaje indeks, gdy określisz pole jako unikalne.

Jegor
źródło
21

Zasadniczo ten błąd mówi, że miałeś unikalny indeks w konkretnym polu, na przykład: „email_address”, więc mongodb oczekuje unikalnej wartości adresu e-mail dla każdego dokumentu w kolekcji.

Powiedzmy, że wcześniej w schemacie unikalny indeks nie był zdefiniowany, a następnie zarejestrowałeś 2 użytkowników z tym samym adresem e-mail lub bez adresu e-mail (wartość zerowa).

Później zobaczyłeś, że był błąd. więc spróbuj to poprawić, dodając unikalny indeks do schematu. Ale twoja kolekcja ma już duplikaty, więc komunikat o błędzie mówi, że nie możesz ponownie wstawić zduplikowanej wartości.

Zasadniczo masz trzy opcje:

  1. Upuść kolekcję

    db.users.drop();

  2. Znajdź dokument o tej wartości i usuń go. Powiedzmy, że wartość była null, możesz ją usunąć za pomocą:

    db.users.remove({ email_address: null });

  3. Upuść unikalny indeks:

    db.users.dropIndex(indexName)

Mam nadzieję, że to pomogło :)

Daksh Miglani
źródło
18

Chcę wyjaśnić odpowiedź / rozwiązanie tego problemu, tak jak wyjaśniam pięciolatkowi, aby każdy mógł zrozumieć.

Mam aplikację. Chcę, aby ludzie rejestrowali się przy użyciu adresu e-mail, hasła i numeru telefonu. W mojej bazie danych MongoDB chcę identyfikować osoby jednoznacznie na podstawie zarówno ich numerów telefonów, jak i wiadomości e-mail - co oznacza, że ​​zarówno numer telefonu, jak i adres e-mail muszą być unikalne dla każdej osoby.

Istnieje jednak problem: zdałem sobie sprawę, że każdy ma numer telefonu, ale nie każdy ma adres e-mail.

Ci, którzy nie mają adresu e-mail, obiecali mi, że będą mieli adres e-mail w przyszłym tygodniu. Ale i tak chcę je zarejestrować - więc mówię im, aby kontynuowali rejestrację swoich numerów telefonicznych, gdy zostawiają puste pole wprowadzania adresu e-mail.

Oni to robią.

Moja baza danych POTRZEBUJE unikalnego pola adresu e-mail - ale mam wiele osób z „null” jako adresem e-mail. Więc idę do mojego kodu i mówię schematowi bazy danych, aby zezwalał na puste / zerowe pola adresów e-mail, które później wypełnię unikatowymi adresami e-mail, gdy osoby, które obiecały dodać swoje e-maile do swoich profili w przyszłym tygodniu.

Więc teraz jest to korzystne dla wszystkich (ale dla ciebie; -]): ludzie się rejestrują, cieszę się, że mam ich dane ... a moja baza danych jest szczęśliwa, ponieważ jest ładnie używana ... ale co z tobą? Mam jeszcze podać kod, który utworzył schemat.

Oto kod: UWAGA: Właściwość rzadka w e-mailu mówi mojej bazie danych, aby zezwoliła na wartości zerowe, które później zostaną wypełnione unikatowymi wartościami.

var userSchema = new mongoose.Schema({
  local: {
    name: { type: String },
    email : { type: String, require: true, index:true, unique:true,sparse:true},
    password: { type: String, require:true },
  },
  facebook: {
    id           : { type: String },
    token        : { type: String },
    email        : { type: String },
    name         : { type: String }
  }
});

var User = mongoose.model('User',userSchema);

module.exports = User;

Mam nadzieję, że dobrze to wytłumaczyłem. Szczęśliwego kodowania / hakowania NodeJS!

Daggie Blanqx - Douglas Mwangi
źródło
jeśli chcesz sparseindeks i uniquesprawdzanie poprawności i masz inne pola, które nie są wymagane, musisz użyć tej partialFilterExpressionopcji. Zobacz tę odpowiedź stackoverflow.com/a/34600171/728287
Gianfranco P.
4

W tej sytuacji zaloguj się do Mongo i znajdź indeks, którego już nie używasz (w przypadku OP „e-mail”). Następnie wybierz Drop Index wprowadź opis zdjęcia tutaj

bumsoverboard
źródło
3

Oto moje odradzające doświadczenie:

W schemacie „User” ustawiłem „name” jako unikalny klucz, a następnie uruchomiłem wykonanie, które, jak sądzę, skonfigurowało strukturę bazy danych.

Następnie zmieniłem unikatowy klucz jako „nazwę użytkownika” i nie zapisałem już wartości „nazwa” podczas zapisywania danych w bazie danych. Zatem mongodb może automatycznie ustawić wartość „name” nowego rekordu na null, który jest duplikatem klucza. Próbowałem ustawić klucz „nazwa” jako klucz unikalny {name: {unique: false, type: String}} w schemacie „Użytkownik”, aby zastąpić oryginalne ustawienie. Jednak to nie zadziałało.

W końcu stworzyłem własne rozwiązanie:

Wystarczy ustawić losową wartość klucza, która prawdopodobnie nie będzie duplikowana do klucza „nazwa” podczas zapisywania rekordu danych. Po prostu metoda matematyczna '' + Math.random() + Math.random() tworzy losowy ciąg.

Kobe Luo
źródło
12
Nie sądzę, żeby to było prawidłowe rozwiązanie, tylko maskowanie problemu.
Rick
Brzydki, ale pragmatyczny
Anthony
3

Miałem ten sam problem. Próbowanie debugowania na różne sposoby nie było możliwe. Próbowałem upuścić kolekcję i potem wszystko działało dobrze. Chociaż nie jest to dobre rozwiązanie, jeśli Twoja kolekcja ma wiele dokumentów. Ale jeśli jesteś we wczesnym stadium rozwoju, spróbuj upuścić kolekcję.

db.users.drop();
Sandip Subedi
źródło
2

Wynika to z faktu, że istnieje już kolekcja o tej samej nazwie z konfiguracją. Wystarczy usunąć kolekcję z mongodb poprzez powłokę mongo i spróbować ponownie.

db.collectionName.remove ()

teraz uruchom aplikację, powinna działać

Ignacy Andrzej
źródło
2

Miałem podobny problem i zdałem sobie sprawę, że domyślnie mongo obsługuje tylko jeden schemat na kolekcję. Zapisz nowy schemat w innej kolekcji lub usuń istniejące dokumenty z niezgodnym schematem w bieżącej kolekcji. Lub znajdź sposób, aby mieć więcej niż jeden schemat na kolekcję.

Embedded_Mugs
źródło
2

Napotkałem również ten problem i go rozwiązałem. Ten błąd pokazuje, że e-mail jest już tutaj obecny. Musisz więc po prostu usunąć tę linię z atrybutu Model dla wiadomości e-mail.

unique: true

Możliwe, że nawet jeśli to nie zadziała. Wystarczy więc usunąć kolekcję z MongoDB i zrestartować serwer.

Inamur Rahman
źródło
1

Ten sam problem wystąpił, gdy miałem następującą konfigurację w moim pliku config / models.js

module.exports.models = {
  connection: 'mongodb',
  migrate: 'alter'
}

Zmiana migracji z „alter” na „safe” naprawiła to dla mnie.

module.exports.models = {
  connection: 'mongodb',
  migrate: 'safe'
}
Jam Risser
źródło
1

ten sam problem po usunięciu właściwości ze schematu po pierwszym zbudowaniu niektórych indeksów podczas zapisywania. usunięcie właściwości ze schematu prowadzi do wartości pustej dla nieistniejącej właściwości, która wciąż miała indeks. Pomaga tutaj upuszczanie indeksu lub rozpoczynanie od nowej kolekcji od podstaw.

Uwaga: w takim przypadku pojawi się komunikat o błędzie. ma ścieżkę, która już nie istnieje. W moim przypadku stara ścieżka to ... $ uuid_1 (to jest indeks!), ale nowa to .... * priv.uuid_1

chhtm
źródło
1

Miałem ten sam problem, gdy próbowałem zmodyfikować schemat zdefiniowany za pomocą mangoose. Myślę, że problem jest spowodowany tym, że podczas tworzenia kolekcji wykonano pewne podstawowe procesy, takie jak opisywanie indeksów ukrytych przed użytkownikiem (przynajmniej w moim przypadku). Więc najlepszym rozwiązaniem, jakie znalazłem, było usunięcie całej kolekcji i zacznij od nowa.

Rahul P.
źródło
0

Miałem ten sam problem. Problem polegał na tym, że usunąłem jedno pole z modelu. Kiedy upuściłem db to naprawia

użytkownik86168
źródło
0

przyszłym programistom zalecam usunięcie indeksu w INDEX TAB za pomocą kompasu ... NIE USUŃ ŻADNEGO dokumentu w kolekcji Zarządzaj indeksami

Edgar Olivar
źródło
-3

Zmień nazwę kolekcji, jeśli już istnieje w bazie danych, wyświetli błąd. A jeśli podasz dowolną właściwość jako unikalną, wystąpi ten sam błąd.

arul mb
źródło
-4

Miałem ten sam problem, rozwiązałem go, usuwając plik unique atrybut właściwości.

Po prostu znajdź inny sposób sprawdzenia poprawności lub sprawdzenia unikalnych wartości właściwości dla swojego schematu.

davyCode
źródło
Powinieneś podać przykład swojego rozwiązania.
Josh Adams
Najpierw zadziałało czyszczenie kolekcji i / lub usunięcie całej kolekcji z bazy danych mongo, ale było to rozwiązanie tymczasowe. Utworzenie kolejnego rekordu o podobnych wartościach, mimo że miały one różne identyfikatory, nadal dawało błąd klucza E11000. Chciałem zezwolić na duplikowanie wartości dla tej właściwości, więc po prostu usunąłem unikalny atrybut.
davyCode
-7

Wyczyść kolekcję lub Usuń całą kolekcję z bazy danych MongoDB i spróbuj ponownie później.

Vittal Kamkar
źródło