Mongoose: El método de actualización del modelo no respeta los validadores

Creado en 24 abr. 2012  ·  59Comentarios  ·  Fuente: Automattic/mongoose

Puedo usar el método model.Update para actualizar a cualquier valor independientemente de las restricciones del esquema

Por ejemplo, si tengo un esquema con una propiedad de enumeración, al usar la actualización puedo cambiar a cualquier valor fuera de la restricción de enumeración, invalidando así el conjunto.

El comportamiento esperado era arrojar un error si el valor actualizado no se validaba.

Sugiero una opción adicional al método de actualización para salir en el primer error o no.

new feature

Comentario más útil

+1

Es completamente intuitivo que la actualización no usaría: valores predeterminados, establecedores, validación y enumeraciones. ¿De qué sirve un esquema si las operaciones principales no se adhieren a él?

Todos 59 comentarios

es posible que desee habilitar la configuración del esquema strict que ignorará cualquier ruta de esquema no válida y actualizará el resto. no se lanza ningún error.

nuevo esquema ({..}, {estricto: verdadero})

hay una solicitud de extracción similar esperando ser fusionada que se lanza al establecer rutas que no existen en el esquema, pero no se lanza durante model.update . tal vez deberíamos agregar eso al PR anterior y pasar el error a la devolución de llamada.

Hola de nuevo, gracias por tu rápida respuesta.

No me refería a rutas inválidas sino a restricciones dentro de una ruta específica.

Toma este ejemplo

var Usuario = nuevo esquema ({
nombre de usuario: {
tipo: Cadena,
minúsculas: verdadero,
recortar: cierto,
único: verdadero
},
nombre: {
tipo: Cadena,
recortar: cierto,
requerido: cierto,
único: falso,
índice: verdadero
},
contraseña: {
tipo: Cadena,
requerido: cierto,
seleccionar: falso,
conjunto: cifrar
},
rol: {
tipo: Cadena,
"Usuario predeterminado',
"enum": ['usuario', 'admin', 'root']
},
creado: {
tipo: Fecha,
"predeterminado": Date.now
}
}, {estricto: verdadero});

users.update ({"username": "test"}, {"role": "thisShowldFail"}, function (err, val) {
...
});

Observe que ahora el usuario de "prueba" tiene el rol "thisShowldFail" incluso con la opción de esquema estricto habilitada.
¿No debería Update respetar las enumeraciones y otras opciones similares?

Tienes razón, debería validar las enumeraciones. Pensé que había un boleto para esto en alguna parte.

+1, no se puede usar #update debido a este problema.

¿Es posible permitir que .update haga todas las cosas que haría un nuevo documento + .save?

  • valores predeterminados
  • setter
  • validaciones personalizadas
  • enumeración

si se usa la opción upsert, también

  • requerido

no actualmente

Quiero decir, ¿es posible / planeado implementar ...? :)

podría ser agradable. relacionado # 472

+1

Es completamente intuitivo que la actualización no usaría: valores predeterminados, establecedores, validación y enumeraciones. ¿De qué sirve un esquema si las operaciones principales no se adhieren a él?

+1

Me encanta la mangosta, pero si no valida las actualizaciones, es mucho menos útil para mí. Tengo documentos grandes y no quiero descargarlos solo para hacer la validación.

Este soy yo. Me estoy sumergiendo un poco, tratando de implementar esto.
El objetivo es conseguir:

  • valores predeterminados
  • setter
  • validaciones
  • enumeración
  • requerido

Ni siquiera estoy seguro de tener éxito, pero lo intentaré. Empezaré con validadores.

¡Deseame buena suerte!

Merc.

+1

+1

Hubiera sido genial si .update admitieran Validaciones.

Golpe +1

Golpe irregular +1

¡Agregue validaciones en la actualización!

+1

Editar: -2 porque no creo que la mangosta deba hacerse cargo de la validación ... Si desea la validación, debería considerar usar otra biblioteca especializada como una que permite la validación del esquema JSON

@thalesfsp Sí. Se ha intentado en el pasado, pero las reglas se vuelven muy inestables porque no existe ningún documento en la memoria y se rompen en varias circunstancias, lo que deja un comportamiento inconsistente y confuso.

la belleza del código abierto: si desea una función, puede escribirla y enviar una solicitud de extracción con pruebas aprobadas y documentación que demuestre que funciona correctamente.

Una limitación bastante seria. Al buscar un parche, ¿sería práctico simplemente rastrear el objeto Schema directamente para determinar si se debe ejecutar un validador? Me preocupan principalmente los validadores personalizados y las reglas de enumeración que se aplican a la actualización. Las otras restricciones de esquema ya deberían haberse aplicado cuando se guardó el documento, creo. ¿Tiene sentido tal simplificación del problema a solo enumeraciones y validadores y elimina la necesidad de tener cualquier Documento durante la actualización?

+1 Bump, esta sería una característica muy útil: al hacer actualizaciones, me gustaría ver los minutos / máximos, etc., respetados del esquema; de lo contrario, estoy haciendo mucha lógica repetitiva para algo que la mangosta puede hacer

Sería genial ver que esto sucediera. En este momento, mi solución es encontrar el objeto, alterar los campos y luego guardarlo, lo que activa el middleware de validación. Según los documentos :

Tank.findById(id, function (err, tank) {
  tank.size = 'large';
  tank.save(function (err) {
   // Document updated, do something with it
  });
});

Entiendo que esto se complica, ya que el comando update delega directamente a Mongo, y el documento completo no se guarda en la memoria para ser validado. Por lo tanto, el enfoque sugerido por @BrianHoldsworth parece un buen lugar para comenzar, analizando el esquema que ejecuta validaciones solo contra los campos que se van a actualizar.

@aheckmann, ¿ podría proporcionarnos más detalles sobre los esfuerzos de implementación anteriores (fallidos) para que quien intente este parche no vuelva a cometer los mismos errores?

Me preocupan principalmente los validadores personalizados y las reglas de enumeración que se aplican a la actualización. Las otras restricciones de esquema ya deberían haberse aplicado cuando se guardó el documento, creo. ¿Tiene sentido tal simplificación del problema a solo enumeraciones y validadores y elimina la necesidad de tener cualquier Documento durante la actualización?

@BrianHoldsworth Creo que esto podría ser una simplificación excesiva. ¿Qué sucede si un campo con una restricción de validación required: true se actualiza para ser una cadena vacía? Necesitaríamos esto para disparar un error de validación.

También me interesa esto. ¿Quizás se podría escribir un complemento para anular el método .update () y ejecutar la validación? De esa forma, se puede implementar incluso una solución parcial. Si estuviera en el núcleo, por otro lado, se esperaría que manejara todo tipo de validación y fuera 100% robusto.

También me he encontrado con esto, con validadores personalizados y enumeraciones. Si bien es posible buscar y luego actualizar, hace que sea muy difícil escribir código de caso general cuando los documentos tienen diferentes estructuras de subdocumentos.

+1 golpea esto.

La solución de Brian parece bastante elegante. Me encantaría recibir una notificación cuando los parches lleguen a la versión beta.

+1

necesito este +1

+1

+1

+1

+1

En 3.9.3 update() tendrá 2 opciones especiales, setDefaultsOnInsert y runValidators , que establecerán valores predeterminados y ejecutarán validadores en su consulta. Vea las pruebas, por ejemplo, aún no hay documentos reales :(

Muchas gracias, ¡esta es una gran solución!

@ vkarpov15 Usé su código para aplicar también la validación a findOneAndUpdate. Ver PR # 2393.

Hola, ¿sabes cuándo se lanzará la versión estable 3.9 para usar la validación en la actualización?

Gracias

@AlexandreAWE buena pregunta. Actualmente estoy terminando las cosas en 4.0 y probando beta la rama 3.9.x, pero ahora mismo es una cosa de "estará hecho cuando esté hecho". Espero tener un RC antes de Navidad.

@ vkarpov15 ¿Cómo te va en el establo 3.9.x? Sería genial tener validaciones en la actualización en lugar de buscar y guardar cada vez para mi proyecto actual.

@andrewholsted esperando que el controlador 2.0 de mongodb y el servidor 2.8 de mongodb se estabilicen; es de esperar que eso suceda este mes, pero realmente no se puede enviar 4.0 sin admitir la última versión de mongodb y el controlador más reciente. Vea mi blog para más detalles.

Una pregunta potencialmente tonta de mi parte, pero ¿por qué no tomar los datos que se actualizan y validarlos con el esquema antes de pasar a mongodb?

Además, +1

marcar y esperar

No puedo esperar hasta que 3.9 sea estable :)

¿Esta característica ya está disponible? Esperando ansiosamente 3.9 .. ¿Wen estará disponible?

Puede npm install mongoose@unstable para obtener la versión inestable. La ETA actual para 4.0 es el 25 de marzo; un buen lugar para consultar esta es la página de hitos

Me encontré con este problema anoche. ¡Me alegro de no ser el único! Estoy emocionado de que se publique este cambio, ¡gracias por todo lo que hacen!

+1

No sé por qué este problema está marcado como cerrado. Todavía lo estoy enfrentando.

En realidad, no estoy seguro de que esto funcione en la validación de enumeración para findOneAndUpdate (), incluso con runValidators establecido en verdadero.

@ m1cah , proporcione un ejemplo que demuestre lo que está tratando de hacer. Tenemos pruebas para esto y pasan ...

@ vkarpov15 Creo que este es un breve ejemplo que lo demuestra: http://code.runnable.com/VYhGbVhereIYdbst/update-validation-enum-for-mongoose-and-databases

Bueno, un problema es que el ejemplo anterior usa una versión prehistórica de mangosta:

root<strong i="6">@runnable</strong>:~# head node_modules/mongoose/package.json                                                                                                                 
{                                                                                                                                                                         
  "name": "mongoose",                                                                                                                                                     
  "description": "Elegant MongoDB object modeling for Node.js",                                                                                                           
  "version": "3.6.14",                                                                                                                                                    
  "author": {                                                                                                                                                             
    "name": "Guillermo Rauch",                                                                                                                                            
    "email": "[email protected]"                                                                                                                                   
  },                                                                                                                                                                      
  "keywords": [                                                                                                                                                           
    "mongodb",  

Intente actualizar a 4.xy debería funcionar.

¿Está seguro de que funciona con un método enum y findOneAndUpdate?
En mangosta 4.2.6 parece fallar, puedo establecer un valor incorrecto.

Esquema:

var UserSchema = new Schema({
    first_name: {
        type: String,
        required: true,
    },
    last_name: {
        type: String,
        required: true,
    },
    email: {
        type: String,
        unique: true,
        required: true,
    },
    embededData: [{
        type: {
            type: String,
            enum: ['value1', 'value2', 'value3']
            required: true
        }
    }]
}, { strict: true });

Método FindOneAndUpdate:

UserModel.findOneAndUpdate(
    {_id: uid}, 
    {$push: {embededData: data}}, 
    { runValidators: true }, function(err) {
});

Entonces puedo presionar embededData.type = 'Panda';

Consulte los documentos del validador de actualización y # 2933: los validadores de actualización no se ejecutan en $push , solo en $set y $unset

+1

Por lo que puedo ver, esto todavía no funciona para el caso en el que está utilizando un validador personalizado en un campo que es una matriz.

Por ejemplo, este fragmento de código:

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/myTestDB');

var db = mongoose.connection;

db.on('error', function (err) {
console.log('connection error', err);
});
db.once('open', function () {
console.log('connected.');
});

var Schema = mongoose.Schema;
var userSchema = new Schema({
  _id : String,
  name : {
    type: [String],
    validate: {
        validator: function (str) {
            return str.length > 1
        }
    },
  }
});


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

User.findOneAndUpdate({"name": ["John", "Doe"]}, { 
  $setOnInsert: {
    name: ["John"],
  },
}, { runValidators: true, upsert: true, new: true }, function (err, data) {
  if (err) {
    return console.log(err);
  } else {
    // console.log(data.validateSync())
    return console.log('Updated', data);
  }
});

le permitirá actualizar al usuario para que tenga un campo name de ["John"] sin arrojar ningún error, aunque el validador personalizado que incluí prohíbe explícitamente cualquier matriz de nombre de longitud menor o igual a 1. El El validador en sí funciona bien, como puede verse por el hecho de que si quita el comentario de la línea console.log(data.validateSync()) , forzando así que se lleve a cabo la validación, de hecho devolverá el mensaje de error correspondiente. El problema es que esta validación no se lleva a cabo dentro de la llamada findOneAndUpdate() , a pesar de que incluyo la opción runValidators=true .

Parece un error, ¿puede abrir un problema separado para eso?

Gracias

¿Hay alguna solución disponible para el problema anterior? @ vkarpov15

@ Saravanan90 por favor deje de comentar sobre temas cerrados durante mucho tiempo sin ninguna información significativa. Abra un problema separado con ejemplos de código.

¿Fue útil esta página
0 / 5 - 0 calificaciones