E11000 índice de error de clave duplicada en mongodb mongoose

Resuelto Trialcoder asked hace 10 años • 24 respuestas

El siguiente es mi useresquema en user.jsel modelo:

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

Revisé la colección de bases de datos y no existe ninguna entrada duplicada. Déjame saber qué estoy haciendo mal.

Para su información, req.body.emaily req.body.passwordestán obteniendo valores.

También revisé esta publicación pero no encontré ayuda STACK LINK

Si lo eliminé por completo, inserta el documento; de lo contrario, arroja el error "Duplicado" incluso si tengo una entrada en el correo electrónico local.

Trialcoder avatar Jun 26 '14 19:06 Trialcoder
Aceptado

El mensaje de error dice que ya existe un registro con nullel correo electrónico. En otras palabras, ya tienes un usuario sin 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 creació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 de índice contiene un valor nulo.

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

índices escasos


De comentarios:

Su error dice que la clave tiene nombre, mydb.users.$email_1lo que me hace sospechar que tiene un índice tanto en users.emailcomo users.local.email(el primero es antiguo y no se usa en este momento). Eliminar un campo de un modelo Mongoose no afecta la base de datos. Verifique mydb.users.getIndexes()si este es el caso y elimine manualmente el índice no deseado con mydb.users.dropIndex(<name>).

RickN avatar Jun 26 '2014 12:06 RickN

Si todavía se encuentra en su entorno de desarrollo, eliminaría 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
Rick avatar Sep 13 '2015 14:09 Rick

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 la gente se registre 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 forma única en función de sus números de teléfono y correo electrónico; por lo tanto, 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 todo el mundo tiene un número de teléfono pero no todo el mundo tiene una dirección de correo electrónico.

Aquellos que no tienen una dirección de correo electrónico me han prometido que la tendrán 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 mientras 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 al esquema de mi base de datos que permita campos de direcciones de correo electrónico vacíos/nulos que luego completaré con direcciones de correo electrónico únicas cuando las personas que prometieron agregar sus correos electrónicos a sus perfiles la próxima semana.

Así que ahora es beneficioso para todos (menos para usted ;-]): las personas se registran, yo estoy feliz de tener sus datos... y mi base de datos está feliz porque se está utilizando bien... pero ¿y usted? Todavía tengo que darte el código que creó 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 completará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;
Expandir fragmento

Espero haberlo explicado bien. ¡Feliz codificación/hackeo de NodeJS!