Índice de erro de chave duplicada E11000 no mongodose mongodb

229

A seguir está meu useresquema no user.jsmodelo -

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;

É assim que eu estou usando no meu controlador -

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

É assim que eu estou salvando no 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"});
    }
});

Erro -

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

Eu verifiquei a coleção db e não existe essa entrada duplicada, deixe-me saber o que estou fazendo de errado?

FYI - req.body.emaile req.body.passwordestão buscando valores.

Eu também verifiquei este post, mas não ajuda STACK LINK

Se eu removi completamente, em seguida, ele insere o documento, caso contrário, gera o erro "Duplicar", mesmo que eu tenha uma entrada no local.email

Trialcoder
fonte
1
Teve o mesmo erro! Durante o desenvolvimento, desabilitamos a indexação automática e estávamos usando nomes / chaves de esquema em minúsculas. Mais tarde, decidimos usar o TitleCase, mas não atualizamos nossos nomes de índice (por exemplo: titleCase em vez de TitleCase). Então, quando ativamos a indexação, recebemos esse erro. Demorou um pouco para descobrir. Você deseja garantir que todos os nomes / chaves sejam nomeados exatamente em todos os lugares.
Jeach
6
Eu tive o mesmo erro e definir o modelo do mangusto para unique: falsenão estava tendo nenhum impacto. Percebi que tinha que primeiro largar a mesa e depois funcionaria. Você pode fazer algo parecido db.whateverthecollection.drop({}). Cuidado, ele exclui a coleção.
Pere
1
_id: mongoose.Types.ObjectId é adicionado porque é necessária uma identificação única
Mayank Pandav 20/03

Respostas:

241

A mensagem de erro está dizendo que já existe um registro nullcomo email. Em outras palavras, você já tem um usuário sem um endereço de email.

A documentação relevante para isso:

Se um documento não tiver um valor para o campo indexado em um índice exclusivo, o índice armazenará um valor nulo para este documento. Devido à restrição exclusiva, o MongoDB permitirá apenas um documento que não possui o campo indexado. Se houver mais de um documento sem um valor para o campo indexado ou estiver faltando o campo indexado, a criação do índice falhará com um erro de chave duplicado.

Você pode combinar a restrição exclusiva com o índice esparso para filtrar esses valores nulos do índice exclusivo e evitar o erro.

índices únicos

Os índices esparsos contêm apenas entradas para documentos que possuem o campo indexado, mesmo que o campo de índice contenha um valor nulo.

Em outras palavras, um índice esparso é aceitável com vários documentos, todos com nullvalores.

índices esparsos


Dos comentários:

Seu erro diz que a chave é nomeada, o mydb.users.$email_1que me faz suspeitar que você tenha um índice em ambos users.emaile users.local.email(o primeiro está velho e não é usado no momento). A remoção de um campo de um modelo do Mongoose não afeta o banco de dados. Verifique mydb.users.getIndexes()se esse é o caso e remova manualmente o índice indesejado com mydb.users.dropIndex(<name>).

RickN
fonte
1
Eu só removeu esse documento nulo e funcionou :) +1 ..thx para a ajuda
Trialcoder
70
Seu erro diz que a chave é nomeada, o mydb.users.$email_1que me faz suspeitar que você tenha um índice em ambos users.emaile users.local.email(o primeiro está velho e não é usado no momento). A remoção de um campo de um modelo do Mongoose não afeta o banco de dados. Verifique mydb.users.getIndexes()se esse é o caso e remova manualmente o índice indesejado com mydb.users.dropIndex(<name>).
RickN
17
Ou o uso db.users.dropIndexes()se você estiver fazendo várias alterações de índice
cs_stackX
1
Esse foi um problema para mim quando estava usando o plugin mongoose passport-local-mongoose sem definir um nome de usuário para novos usuários.
Sshow 23/01
1
É uma questão ou perspectiva ou talvez até opinião, @titoih - é nulo ou a ausência de um valor é um valor igual a qualquer outro ou é um caso especial? "a @ bc" e "a @ bc" são iguais, "nada" e "nada" são iguais? Com um índice não esparso, a resposta é "sim" no MongoDB. Outros bancos de dados (como o MySQL) diriam "não".
RickN 26/04
65

Se você ainda estiver em seu ambiente de desenvolvimento, eu descartaria o banco de dados inteiro e começaria novamente com seu novo esquema.

Na linha de comando

 mongo
use dbName;
db.dropDatabase();
exit
Rick
fonte
47
Eu acho que esta solução é muito agressivo, eu acho que é o suficiente com db.collection.dropIndexes()a cs_stackX disse
JorgeGarza
2
@JorgeGarza Eu tive o mesmo problema. Acabei de largar a coleção e tudo começou a funcionar bem depois disso.
Sandip Subedi
Inicializei acidentalmente a coleção com um ID exclusivo para dois dos meus campos. Mais tarde, quando quis adicionar vários documentos com o mesmo ID, não me deixou até excluir a coleção e acessá-la novamente.
Meir Snyder
1
Se você é novo no seu desenvolvimento, é uma boa chance de experimentar e descobrir como resolver isso ... em vez de se deparar com esse problema depois de ter gigabytes de dados do usuário já armazenados
Janac Meena
O comentário de @JorgeGarza faz sentido. Os índices descartados serão reconstruídos novamente pelo arquivo Schema quando o servidor for reiniciado. Além disso, funcionou.
retr0
26

Verifique os índices de coleção.

Eu tive esse problema devido a índices desatualizados na coleção de campos, que devem ser armazenados por um novo caminho diferente.

O Mongoose adiciona índice quando você especifica o campo como exclusivo.

Yegor
fonte
22

Bem, basicamente, este erro está dizendo, que você tinha um índice exclusivo em um campo específico, por exemplo: "email_address", então o mongodb espera um valor exclusivo de endereço de email para cada documento da coleção.

Por exemplo, no seu esquema, o índice exclusivo não foi definido e, em seguida, você inscreveu 2 usuários com o mesmo endereço de email ou sem endereço de email (valor nulo).

Mais tarde, você viu que houve um erro. então você tenta corrigi-lo adicionando um índice exclusivo ao esquema. Como sua coleção já possui duplicatas, a mensagem de erro informa que você não pode inserir um valor duplicado novamente.

Você tem essencialmente três opções:

  1. Descartar a coleção

    db.users.drop();

  2. Encontre o documento que possui esse valor e exclua-o. Digamos que o valor fosse nulo, você pode excluí-lo usando:

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

  3. Solte o índice exclusivo:

    db.users.dropIndex(indexName)

Espero que isso tenha ajudado :)

Daksh Miglani
fonte
20

Quero explicar a resposta / solução para isso, como estou explicando a uma criança de 5 anos, para que todos possam entender.

Quero que as pessoas se registrem com seu e-mail, senha e número de telefone. No meu banco de dados do MongoDB, quero identificar pessoas exclusivamente com base em seus números de telefone e email - portanto, isso significa que tanto o número de telefone quanto o email devem ser exclusivos para cada pessoa.

No entanto, há um problema: percebi que todo mundo tem um número de telefone, mas nem todo mundo tem um endereço de email.

Aqueles que não têm um endereço de e-mail me prometeram que terão um endereço de e-mail até a próxima semana. Mas eu quero que eles sejam registrados de qualquer maneira - então eu digo para eles continuarem registrando seus números de telefone enquanto deixam o campo de entrada de email vazio.

Eles fazem isso.

Meu banco de dados PRECISA de um campo de endereço de email exclusivo - mas eu tenho muitas pessoas com 'null' como endereço de email. Então, vou ao meu código e digo ao esquema do banco de dados para permitir campos de endereço de email vazios / nulos que posteriormente preencherei com endereços exclusivos de email quando as pessoas que prometeram adicionar seus emails a seus perfis na próxima semana.

Portanto, agora é uma vantagem para todos (exceto você; -]): as pessoas se registram, fico feliz por ter seus dados ... e meu banco de dados está feliz porque está sendo usado com bom gosto ... mas e você? Ainda estou para fornecer o código que criou o esquema.

Aqui está o código: NOTA: A propriedade esparsa no email é o que diz ao meu banco de dados para permitir valores nulos que posteriormente serão preenchidos com valores exclusivos.

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;

Espero ter explicado bem. Feliz NodeJS codificação / hacking!

Daggie Blanqx - Douglas Mwangi
fonte
se você deseja um sparseíndice e uniquevalidação e possui outros campos que não são necessários, precisará usar a partialFilterExpressionopção Veja esta resposta stackoverflow.com/a/34600171/728287
Gianfranco P.
4

Nessa situação, faça logon no Mongo e encontre o índice que você não está mais usando (no caso do OP 'email'). Em seguida, selecione Drop Index insira a descrição da imagem aqui

prancha de surf
fonte
3

Esta é a minha experiência relevante:

No esquema 'Usuário', defino 'nome' como chave exclusiva e, em seguida, executei alguma execução, que acho que configurou a estrutura do banco de dados.

Alterei a chave exclusiva como 'nome de usuário' e não passei mais o valor 'nome' quando salvei os dados no banco de dados. Portanto, o mongodb pode definir automaticamente o valor 'nome' do novo registro como nulo, que é uma chave duplicada. Tentei a chave 'nome' definida como chave não exclusiva {name: {unique: false, type: String}}no esquema 'Usuário' para substituir a configuração original. No entanto, não funcionou.

Por fim, fiz minha própria solução:

Basta definir um valor de chave aleatória que provavelmente não será duplicado para a chave 'name' quando você salvar seu registro de dados. O método Simply Math '' + Math.random() + Math.random() cria uma sequência aleatória.

Kobe Luo
fonte
12
Eu não acho que essa seja uma solução válida, você está apenas ocultando o problema.
Rick Rick
Feio, mas pragmático
Anthony
3

Eu tive o mesmo problema. Tentei depurar maneiras diferentes não consegui descobrir. Tentei largar a coleção e funcionou bem depois disso. Embora essa não seja uma boa solução, se sua coleção tiver muitos documentos. Mas se você estiver no estado inicial de desenvolvimento, tente descartar a coleção.

db.users.drop();
Sandip Subedi
fonte
2

Isso ocorre porque já existe uma coleção com o mesmo nome na configuração .. Basta remover a coleção do seu mongodb através do shell do mongo e tente novamente.

db.collectionName.remove ()

agora execute seu aplicativo, ele deve funcionar

Inácio André
fonte
2

Eu tive um problema semelhante e percebi que, por padrão, o mongo suporta apenas um esquema por coleção. Armazene seu novo esquema em uma coleção diferente ou exclua os documentos existentes com o esquema incompatível na sua coleção atual. Ou encontre uma maneira de ter mais de um esquema por coleção.

Embedded_Mugs
fonte
2

Eu também enfrentei esse problema e resolvi-o. Este erro mostra que o email já está presente aqui. Então, você só precisa remover esta linha do seu atributo Model for email.

unique: true

Pode ser possível que, mesmo que não funcione. Então, basta excluir a coleção do seu MongoDB e reiniciar o servidor.

Inamur Rahman
fonte
1

Eu tive esse mesmo problema quando tive a seguinte configuração em meu config / models.js

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

Alterar a migração de 'alter' para 'safe' corrigiu isso para mim.

module.exports.models = {
  connection: 'mongodb',
  migrate: 'safe'
}
Jam Risser
fonte
1

mesmo problema após remover as propriedades de um esquema após criar primeiro alguns índices ao salvar. remover a propriedade do esquema leva a um valor nulo para uma propriedade não existente, que ainda tinha um índice. soltar o índice ou começar com uma nova coleção do zero ajuda aqui.

nota: a mensagem de erro levará você nesse caso. tem um caminho que não existe mais. No meu caso, o caminho antigo era ... $ uuid_1 (este é um índice!), mas o novo é .... * priv.uuid_1

chhtm
fonte
1

Eu tive o mesmo problema quando tentei modificar o esquema definido usando mangoose. Penso que o problema se deve ao motivo de haver algum processo subjacente ao criar uma coleção, como descrever os índices ocultos do usuário (pelo menos no meu caso) .Então, a melhor solução encontrada foi descartar a coleção inteira e comece de novo.

Rahul P
fonte
0

Eu tive o mesmo problema. O problema foi que removi um campo do modelo. Quando eu larguei db ele corrige

user86168
fonte
0

para futuros desenvolvedores, eu recomendo, exclua o índice na INDEX TAB usando a bússola ... isso NÃO EXCLUI QUALQUER documento em sua coleção Gerenciar índices

Edgar Olivar
fonte
-3

Altere o nome da coleção, se ele já existir no banco de dados, ele mostrará um erro. E se você forneceu alguma propriedade como única, o mesmo erro ocorrerá.

arul mb
fonte
-4

Teve o mesmo problema que eu resolvi removendo o uniqueatributo na propriedade.

Basta encontrar outra maneira de validar ou verificar valores de propriedades exclusivos para seu esquema.

davyCode
fonte
Você deve fornecer um exemplo com sua solução.
21418 Josh Adams #
Primeiro, limpando a coleção e / ou excluindo toda a coleção do banco de dados mongo funcionou, embora fosse uma solução temporária. A criação de outro registro com valores semelhantes, mesmo que tivessem IDs diferentes, ainda gerou um erro de chave duplicada no E11000. Eu queria permitir valores duplicados para essa propriedade, então simplesmente removi o atributo exclusivo.
DavidCode 03/02
-7

Limpe a coleção ou Exclua a coleção inteira do banco de dados MongoDB e tente novamente mais tarde.

Vittal Kamkar
fonte