E11000 índice de error de clave duplicada en mongodb mongoose

229

El siguiente es mi useresquema en el 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;

Así es como lo estoy usando en mi controlador:

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

Así es como lo estoy guardando en la base de datos:

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"});
    }
});

error -

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

Verifiqué la colección de db y no existe tal entrada duplicada, ¿me avisas qué estoy haciendo mal?

FYI - req.body.emaily req.body.passwordestán obteniendo valores.

También revisé esta publicación pero no ayudé STACK LINK

Si eliminé completamente, entonces inserta el documento, de lo contrario arroja el error "Duplicar" incluso si tengo una entrada en el correo electrónico local.

Trialcoder
fuente
1
Tenía el mismo error! Durante el desarrollo, deshabilitamos la indexación automática y utilizamos claves / nombres de esquema en minúsculas. Más tarde decidimos usar TitleCase en su lugar, pero no pudimos actualizar nuestros nombres de índice (es decir: titleCase en lugar de TitleCase). Entonces, cuando habilitamos la indexación, obtuvimos este error. Tomó un poco de tiempo resolverlo. Deberá asegurarse de que todos los nombres / claves estén nombrados exactamente en todas partes.
Jeach
66
Tuve el mismo error y establecer el modelo de mangosta unique: falseno estaba teniendo ningún impacto. Me di cuenta de que primero tenía que dejar caer la mesa y luego funcionaría. Puedes hacer algo como db.whateverthecollection.drop({}). Tenga cuidado, elimina la colección.
Pere
1
_id: mongoose.Types.ObjectId add porque se requiere una identificación única
Mayank Pandav

Respuestas:

241

El mensaje de error dice que ya hay un registro con nullel correo electrónico. En otras palabras, ya tiene un usuario sin una dirección de correo electrónico.

La documentación relevante para esto:

Si un documento no tiene un valor para el campo indexado en un índice único, el índice almacenará un valor nulo para este documento. Debido a la restricción única, MongoDB solo permitirá un documento que carezca del campo indexado. Si hay más de un documento sin un valor para el campo indexado o falta el campo indexado, la compilación del índice fallará con un error de clave duplicada.

Puede combinar la restricción única con el índice disperso para filtrar estos valores nulos del índice único y evitar el error.

índices únicos

Los índices dispersos solo contienen entradas para documentos que tienen el campo indexado, incluso si el campo índice contiene un valor nulo.

En otras palabras, un índice disperso está bien con varios documentos que tienen nullvalores.

índices escasos


De comentarios:

Su error dice que se nombra la clave, lo mydb.users.$email_1que me hace sospechar que tiene un índice en ambos users.emaily users.local.email(el primero está viejo y sin usar en este momento). Eliminar un campo de un modelo Mongoose no afecta a la base de datos. Compruebe mydb.users.getIndexes()si este es el caso y elimine manualmente el índice no deseado con mydb.users.dropIndex(<name>).

RickN
fuente
1
Acabo de eliminar ese documento nulo y funcionó :) +1 ..thx por la ayuda
Trialcoder
70
Su error dice que se nombra la clave, lo mydb.users.$email_1que me hace sospechar que tiene un índice en ambos users.emaily users.local.email(el primero está viejo y sin usar en este momento). Eliminar un campo de un modelo Mongoose no afecta a la base de datos. Compruebe mydb.users.getIndexes()si este es el caso y elimine manualmente el índice no deseado con mydb.users.dropIndex(<name>).
RickN
17
O db.users.dropIndexes()
úselo
1
Este fue un problema para mí cuando estaba usando el complemento mongoose passport-local-mongoose sin establecer un nombre de usuario para los nuevos usuarios.
mostrar el
1
Es una cuestión o perspectiva o tal vez incluso una opinión, @titoih: ¿es nulo o la ausencia de un valor un valor como cualquier otro o es un caso especial? "a @ bc" y "a @ bc" son lo mismo, ¿son "nada" y "nada" lo mismo también? Con un índice no disperso, la respuesta es "sí" en MongoDB. Otras bases de datos (como MySQL) dirían "no".
RickN
65

Si todavía está en su entorno de desarrollo, dejaría caer toda la base de datos y comenzaría de nuevo con su nuevo esquema.

Desde la línea de comando

 mongo
use dbName;
db.dropDatabase();
exit
Almiar
fuente
47
Creo que esta solución es muy agresiva, creo que es suficiente con lo db.collection.dropIndexes()que dijo
cs_stackX
2
@JorgeGarza Tuve el mismo problema. Acabo de dejar caer la colección y todo comenzó a funcionar bien después de eso.
Sandip Subedi
Accidentalmente inicialicé la colección con una identificación única para dos de mis campos. Más tarde, cuando quise agregar varios documentos con el mismo Id. No me permitió hasta que eliminé la colección y volví a acceder.
Meir Snyder
1
Si es nuevo en su desarrollo, esta es una buena oportunidad para experimentar y descubrir cómo resolver esto ... en lugar de encontrarse con este problema una vez que tenga gigabytes de datos de usuario ya almacenados
Janac Meena
El comentario de @JorgeGarza tiene sentido. Los índices descartados serán reconstruidos nuevamente por el archivo de esquema cuando se reinicie el servidor. Además, funcionó.
retr0
26

Verifique los índices de recolección.

Tuve ese problema debido a los índices obsoletos en la colección de campos, que deberían almacenarse en una nueva ruta diferente.

Mongoose agrega índice, cuando especifica el campo como único.

Yegor
fuente
22

Básicamente, este error dice que tenía un índice único en un campo en particular, por ejemplo: "dirección_de_email", por lo que mongodb espera un valor de dirección de correo electrónico único para cada documento de la colección.

Entonces, digamos, anteriormente en su esquema, el índice único no estaba definido, y luego inscribió a 2 usuarios con la misma dirección de correo electrónico o sin dirección de correo electrónico (valor nulo).

Más tarde, viste que hubo un error. entonces intenta corregirlo agregando un índice único al esquema. Pero su colección ya tiene duplicados, por lo que el mensaje de error dice que no puede volver a insertar un valor duplicado.

Básicamente tienes tres opciones:

  1. Suelta la colección

    db.users.drop();

  2. Encuentre el documento que tiene ese valor y elimínelo. Digamos que el valor era nulo, puede eliminarlo usando:

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

  3. Suelte el índice único:

    db.users.dropIndex(indexName)

Espero que esto haya ayudado :)

Daksh Miglani
fuente
20

Quiero explicar la respuesta / solución a esto como se lo estoy explicando a un niño de 5 años, para que todos puedan entender.

Tengo una aplicación. Quiero que las personas se registren con su correo electrónico, contraseña y número de teléfono. En mi base de datos MongoDB, quiero identificar a las personas de manera única en función de sus números de teléfono y correo electrónico, por lo que esto significa que tanto el número de teléfono como el correo electrónico deben ser únicos para cada persona.

Sin embargo, hay un problema: me he dado cuenta de que todos tienen un número de teléfono, pero no todos tienen una dirección de correo electrónico.

Los que no tienen una dirección de correo electrónico me han prometido que tendrán una dirección de correo electrónico la próxima semana. Pero quiero que se registren de todos modos, así que les digo que continúen registrando sus números de teléfono, ya que dejan el campo de entrada de correo electrónico vacío.

Ellos lo hacen

Mi base de datos NECESITA un campo de dirección de correo electrónico único, pero tengo muchas personas con 'nulo' como dirección de correo electrónico. Así que voy a mi código y le digo a mi esquema de base de datos que permita campos de dirección de correo electrónico vacíos / nulos que luego completaré con direcciones únicas de correo electrónico cuando las personas que prometieron agregar sus correos electrónicos a sus perfiles la próxima semana.

Así que ahora es un beneficio mutuo para todos (excepto usted; -)): las personas se registran, estoy feliz de tener sus datos ... y mi base de datos está contenta porque se está usando muy bien ... pero ¿y usted? Todavía tengo que darle el código que hizo el esquema.

Aquí está el código: NOTA: La propiedad dispersa en el correo electrónico es lo que le dice a mi base de datos que permita valores nulos que luego se rellenarán con valores únicos.

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 haberlo explicado bien. ¡Feliz codificación / pirateo de NodeJS!

Daggie Blanqx - Douglas Mwangi
fuente
si desea un sparseíndice y uniquevalidación, y tiene otros campos que no son obligatorios, deberá usar la partialFilterExpressionopción. Ver esta respuesta stackoverflow.com/a/34600171/728287
Gianfranco P.
4

En esta situación, inicie sesión en Mongo para encontrar el índice que ya no está utilizando (en el caso de OP, 'correo electrónico'). Luego seleccione Drop Index ingrese la descripción de la imagen aquí

bumsoverboard
fuente
3

Esta es mi experiencia relevante:

En el esquema 'Usuario', configuré 'nombre' como clave única y luego ejecuté algunas ejecuciones, que creo que habían configurado la estructura de la base de datos.

Luego cambié la clave única como 'nombre de usuario' y ya no pasé el valor de 'nombre' cuando guardé datos en la base de datos. Por lo tanto, mongodb puede establecer automáticamente el valor 'nombre' del nuevo registro como nulo, que es una clave duplicada. Intenté establecer la clave 'nombre' como clave no única {name: {unique: false, type: String}} en el esquema 'Usuario' para anular la configuración original. Sin embargo, no funcionó.

Por fin, hice mi propia solución:

Simplemente configure un valor de clave aleatorio que probablemente no se duplicará con la clave 'nombre' cuando guarde su registro de datos. Simplemente método matemático '' + Math.random() + Math.random() hace una cadena aleatoria.

Kobe Luo
fuente
12
No creo que esta sea una solución válida, solo estás enmascarando el problema.
Rick
Feo pero pragmático
Anthony
3

Tuve el mismo problema. Intenté depurar diferentes formas que no podían entender. Intenté dejar caer la colección y funcionó bien después de eso. Aunque esta no es una buena solución si su colección tiene muchos documentos. Pero si está en el estado inicial de desarrollo, intente soltar la colección.

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

Esto se debe a que ya hay una colección con el mismo nombre con configuración ... Simplemente elimine la colección de su mongodb a través de mongo shell e intente nuevamente.

db.collectionName.remove ()

ahora ejecuta tu aplicación, debería funcionar

Ignacio Andrew
fuente
2

Tuve un problema similar y me di cuenta de que, por defecto, mongo solo admite un esquema por colección. Almacene su nuevo esquema en una colección diferente o elimine los documentos existentes con el esquema incompatible dentro de su colección actual. O encuentre una manera de tener más de un esquema por colección.

Embedded_Mugs
fuente
2

También me enfrenté a este problema y lo resolví. Este error muestra que el correo electrónico ya está presente aquí. Por lo tanto, solo necesita eliminar esta línea de su Modelo para el atributo de correo electrónico.

unique: true

Esto podría ser posible incluso si no funciona. Entonces solo necesita eliminar la colección de su MongoDB y reiniciar su servidor.

Inamur Rahman
fuente
1

Tuve este mismo problema cuando tenía la siguiente configuración en mi config / models.js

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

Cambiar migrar de 'alterar' a 'seguro' lo arregló para mí.

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

mismo problema después de eliminar las propiedades de un esquema después de crear algunos índices al guardar. eliminar la propiedad del esquema conduce a un valor nulo para una propiedad no existente, que todavía tenía un índice. ayuda a eliminar el índice o comenzar con una nueva colección desde cero.

nota: el mensaje de error lo llevará en ese caso. tiene un camino que ya no existe. En mi caso, la ruta anterior era ... $ uuid_1 (¡este es un índice!), pero la nueva es ... * priv.uuid_1

chhtm
fuente
1

Tuve el mismo problema cuando intenté modificar el esquema definido con mangoose. Creo que el problema se debe a la razón por la que se realiza un proceso subyacente al crear una colección, como describir los índices que están ocultos para el usuario (al menos en mi caso) .Así que la mejor solución que encontré fue descartar toda la colección y empezar de nuevo

Rahul P
fuente
0

Tuve el mismo problema. El problema fue que eliminé un campo del modelo. Cuando dejé caer db se soluciona

usuario86168
fuente
0

para futuros desarrolladores, les recomiendo, eliminen el índice en la TABLA DE ÍNDICE usando la brújula ... esto NO BORRARÁ NINGÚN documento en su colección Administrar índices

Edgar Olivar
fuente
-3

Cambie el nombre de la colección si ya existe en la base de datos, mostrará un error. Y si proporcionó alguna propiedad como única, se producirá el mismo error.

arul mb
fuente
-4

Tuve el mismo problema, lo resolví eliminando el uniqueatributo de la propiedad.

Simplemente encuentre otra forma de validar o verificar valores de propiedad únicos para su esquema.

davyCode
fuente
Debe proporcionar un ejemplo con su solución.
Josh Adams
Primero, limpiar la colección y / o eliminar toda la colección de la base de datos mongo funcionó, sin embargo, fue una solución temporal. La creación de otro registro con valores similares a pesar de que tenían identificaciones diferentes todavía dio un error de clave duplicada E11000. Quería permitir valores duplicados para esa propiedad, así que simplemente eliminé el atributo único.
davyCode
-7

Borre la colección o elimine toda la colección de la base de datos MongoDB e intente nuevamente más tarde.

Vittal Kamkar
fuente