mongodb - autoindex - mongoose schema
¡El índice único de Mongoose no funciona! (11)
Oops! Solo tienes que reiniciar mongo.
¡Y volver a indexar también!
En las pruebas, acabo de hacer un:
mongo <db-name>
> db.dropDatabase()
Aunque si tienes datos importantes allí, probablemente solo necesites:
mongo <db-name>
> db.<collection-name>.reIndex()
Intento dejar que MongoDB detecte un valor duplicado según su índice. Creo que esto es posible en MongoDB, pero a través del contenedor Mongoose las cosas parecen estar rotas. Entonces para algo como esto:
User = new Schema ({
email: {type: String, index: {unique: true, dropDups: true}}
})
Puedo guardar 2 usuarios con el mismo correo electrónico. Maldito.
El mismo problema se ha expresado aquí: https://github.com/LearnBoost/mongoose/issues/56 , pero ese hilo es antiguo y no conduce a nada.
Por ahora, estoy haciendo una llamada manual a la base de datos para encontrar al usuario. Esa llamada no es costosa ya que el "correo electrónico" está indexado. Pero aún sería bueno dejar que se maneje de forma nativa.
¿Alguien tiene una solución para esto?
Este comportamiento también ocurre si ha dejado algunos duplicados en Mongo. Mongoose intentará crearlos en Mongo cuando se inicie tu aplicación.
Para evitar esto, puede manejar este error de esta manera:
yourModel.on(''index'', function(err) {
if (err?) {
console.error err
}
);
La respuesta más reciente: no hay necesidad de reiniciar mongodb, si colleciton ya tiene índices del mismo nombre, la mangosta no volverá a crear los índices, por lo tanto, suelte los índices existentes de la recopilación y ahora, cuando ejecute la mangosta, creará un nuevo índice , el proceso anterior resolvió mi problema.
Mangosta es un poco flexible cuando se aplican índices únicos desde el nivel de aplicación; por lo tanto, es preferible imponer sus índices únicos desde la base de datos usando el mongo cli o explícitamente decirle a mongoose que usted es serio acerca del índice unique
al escribir la siguiente línea de código justo después de su UserSchema:
UserSchema.index({ username: 1, email: 1 }, { unique: true});
Esto aplicará el índice único en los campos de username
y email
en su UserSchema. Aclamaciones.
Me encontré con el mismo problema: agregué la restricción única para el campo de email
a nuestro UserSchema
después de haber agregado usuarios a la base de datos, y todavía era capaz de salvar a los usuarios con correos duplicados. Lo resolví haciendo lo siguiente:
1) Eliminar todos los documentos de la colección de usuarios.
2) Desde el shell de mongo, ejecute el comando: db.users.createIndex({email: 1}, {unique: true})
Con respecto al paso 1, ten en cuenta que de los documentos de Mongo:
MongoDB no puede crear un índice único en los campos de índice especificados si la colección ya contiene datos que violarían la restricción única para el índice.
Ok, pude resolver esto desde mongoshell agregando el índice en el campo y estableciendo la propiedad única:
db.<collectionName>.ensureIndex({fieldName: 1}, {unique: true});
Shell debería responder de esta manera:
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
Ahora para probar rápidamente de la mongoshell:
var doc = {fieldName: ''abc''};
db.<collectionName>.insert(doc)
Debería dar: WriteResult ({"nInserted": 1})
Pero cuando repito de nuevo:
db.<collectionName>.insert(doc)
Daré:
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: fuelConsumption.users.$email_1 dup key: { : /"[email protected]/" }"
}
})
Oops! Solo tienes que reiniciar mongo.
Según la documentación: https://docs.mongodb.com/v2.6/tutorial/modify-an-index/
Para modificar un índice existente, debe soltar y volver a crear el índice.
NO REINICIAR MONGO!
1 - soltar la colección
db.users.drop()
2 - reindexar la tabla
db.users.ensureIndex({email: 1, type: 1}, {unique: true})
Si la tabla / colección está vacía, cree un índice único para el campo:
db.<collection_name>.createIndex({''field'':1}, {unique: true})
Si la tabla / colección no está vacía, suelte la colección y cree el índice:
db.<collection_name>.drop()
db.<collection_name>.createIndex({''field'':1}, {unique: true})
Ahora reinicie mongoDB.
También puede resolver este problema al descartar el índice;
supongamos que desea eliminar el índice exclusivo de los users
colección y el username
campo, escriba esto:
db.users.dropIndex(''username_1'');
Cómo usar este plugin:
1) instalación de npm --save mongoose-unique-validator
2) en su esquema siga esta guía:
// 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) métodos de mangosta
Al utilizar métodos como findOneAndUpdate
, deberá pasar este objeto de configuración:
{ runValidators: true, context: ''query'' }
ie. User.findOneAndUpdate(
{ email: ''[email protected]'' },
{ email: ''[email protected]'' },
{ runValidators: true, context: ''query'' },
function(err) {
// ...
}
4) opciones adicionales
case insensible
use la opción uniqueCaseInsensitive en su esquema
ie. email: { type: String, index: true, unique: true, required: true, uniqueCaseInsensitive: true }
mensajes de error personalizados
ie. exampleSchema.plugin(uniqueValidator, { message: ''Error, expected {PATH} to be unique.'' });
Ahora puede agregar / eliminar la propiedad única de sus esquemas sin preocuparse por reiniciar mongo, descartar bases de datos o crear índices.
Advertencias (de los documentos):
Debido a que confiamos en las operaciones asincrónicas para verificar si un documento existe en la base de datos, es posible que se ejecuten dos consultas al mismo tiempo, ambas devuelven 0 y luego ambas se insertan en MongoDB.
Aparte de bloquear automáticamente la colección o forzar una sola conexión, no hay una solución real.
Para la mayoría de nuestros usuarios, esto no será un problema, pero es un caso extremo a tener en cuenta.