Mongoose: La méthode de mise à jour du modèle ne respecte pas les validateurs

Créé le 24 avr. 2012  ·  59Commentaires  ·  Source: Automattic/mongoose

Je peux utiliser la méthode model.Update pour mettre à jour n'importe quelle valeur indépendamment des contraintes de schéma

Par exemple, si j'ai un schéma avec une propriété enum, en utilisant update, je peux changer n'importe quelle valeur en dehors de la contrainte enum, invalidant ainsi l'ensemble.

Le comportement attendu était de générer une erreur si la valeur mise à jour n'était pas validée.

Je suggère une option supplémentaire à la méthode de mise à jour pour quitter ou non la première erreur.

new feature

Commentaire le plus utile

+1

Il n'est pas du tout intuitif que la mise à jour n'utilise pas : valeurs par défaut, setters, validation et énumérations. A quoi sert un schéma si les opérations de base n'y adhèrent pas.

Tous les 59 commentaires

vous souhaiterez peut-être activer le paramètre de schéma strict qui ignorera tous les chemins de schéma invalides et mettra à jour le reste. aucune erreur n'est renvoyée.

nouveau schéma({..}, { strict : vrai })

il y a une demande d'extraction similaire en attente de fusion qui est lancée lors de la définition de chemins qui n'existent pas dans le schéma mais elle n'est pas lancée pendant model.update . peut-être devrions-nous ajouter cela au PR ci-dessus et transmettre l'erreur au rappel.

Re-bonjour, merci pour votre réponse rapide.

Je ne faisais pas référence à des chemins invalides mais à une contrainte au sein d'un chemin spécifique.

Prenons cet exemple

var User = new Schema({
Nom d'utilisateur: {
tapez : chaîne,
minuscule : vrai,
garniture : vrai,
unique : vrai
},
Nom: {
tapez : chaîne,
garniture : vrai,
requis : vrai,
unique : faux,
indice : vrai
},
le mot de passe: {
tapez : chaîne,
requis : vrai,
sélectionnez : faux,
définir : crypter
},
rôle : {
tapez : chaîne,
"Utilisateur par defaut',
"enum": ['utilisateur', 'admin', 'root']
},
créé: {
tapez : Date,
"default": Date.now
}
}, { strict : vrai });

users.update({"nom d'utilisateur" : "test"}, {"rôle" : "thisShowldFail"}, fonction (err, val){
...
});

Notez que maintenant l'utilisateur "test" a le rôle "thisShowldFail" même avec l'option de schéma strict activée.
La mise à jour ne devrait-elle pas respecter les énumérations et autres options similaires ?

Vous avez raison, cela devrait valider les énumérations. Je pensais qu'il y avait un ticket pour ça quelque part.

+1, impossible d'utiliser #update à cause de ce problème.

Est-il possible de laisser .update faire tout ce qu'un nouveau document + .save ferait ?

  • valeurs par défaut
  • setter
  • validations personnalisées
  • énumérer

si l'option upsert est utilisée, également

  • obligatoire

pas actuellement

Je veux dire est-il possible/prévu de mettre en œuvre ... ? :)

ça peut être sympa. lié #472

+1

Il n'est pas du tout intuitif que la mise à jour n'utilise pas : valeurs par défaut, setters, validation et énumérations. A quoi sert un schéma si les opérations de base n'y adhèrent pas.

+1

J'adore la mangouste mais si elle ne valide pas les mises à jour elle m'est beaucoup moins utile. J'ai de gros documents et je ne veux pas les télécharger juste pour valider.

C'est moi qui saute dedans. Je plonge un peu, essayant de mettre cela en œuvre.
Le but est d'obtenir :

  • valeurs par défaut
  • setter
  • validations
  • énumérer
  • obligatoire

Je ne suis même pas sûr de réussir, mais je vais essayer. Je vais commencer par les validateurs.

Souhaite moi bonne chance!

Merc.

+1

+1

Cela aurait été génial si .update pris en charge les validations.

Coup +1

bosse bosselée +1

Veuillez ajouter des validations lors de la mise à jour !

+1

Edit: -2 parce que je ne pense pas que mongoose devrait prendre en charge la validation. Si vous voulez une validation, vous devriez envisager d'utiliser une autre bibliothèque spécialisée comme celle qui permet la validation JSON Schema

@thalesfsp Oui. Cela a été tenté dans le passé, mais les règles deviennent très bancales car aucun document n'existe en mémoire et tombent en panne dans plusieurs circonstances, laissant un comportement incohérent et déroutant.

la beauté de l'open source : si vous voulez une fonctionnalité, vous pouvez l'écrire et soumettre une pull request avec des tests réussis et une documentation qui prouve qu'elle fonctionne correctement.

Une limitation assez sérieuse. Lors de la recherche d'un correctif, serait-il pratique de simplement analyser l'objet Schema directement pour déterminer si un validateur doit être exécuté ? Je me soucie principalement des validateurs personnalisés et des règles d'énumération appliquées à la mise à jour. Les autres contraintes de schéma auraient déjà dû être appliquées lors de l'enregistrement du document, je pense. Une telle simplification du problème jusqu'aux énumérations et validateurs a-t-elle un sens et supprime-t-elle le besoin d'avoir un document pendant la mise à jour ?

+1 Bump, ce serait une fonctionnalité très utile - lors des mises à jour, j'aimerais voir les min/maxes etc. respectés à partir du schéma - sinon je fais beaucoup de logique passe-partout pour quelque chose que la mangouste peut faire

Ce serait formidable de voir cela se produire. Pour le moment, ma solution de contournement consiste à trouver l'objet, à modifier les champs, puis à l'enregistrer, ce qui déclenche le middleware de validation. D'après la doc :

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

Je comprends que cela soit compliqué, car la commande update délègue directement à Mongo, et le document complet ne reste pas en mémoire pour être validé. Ainsi, l'approche suggérée par @BrianHoldsworth semble être un bon point de départ, en analysant le schéma exécutant les validations uniquement par rapport aux champs qui doivent être mis à jour.

@aheckmann pourriez-vous nous fournir plus de détails sur les efforts de mise en œuvre précédents (échecs) afin que quiconque tente ce correctif ne fasse plus les mêmes erreurs ?

Je me soucie principalement des validateurs personnalisés et des règles d'énumération appliquées à la mise à jour. Les autres contraintes de schéma auraient déjà dû être appliquées lors de l'enregistrement du document, je pense. Une telle simplification du problème jusqu'aux énumérations et validateurs a-t-elle un sens et supprime-t-elle le besoin d'avoir un document pendant la mise à jour ?

@BrianHoldsworth Je pense que cela pourrait être une simplification excessive. Que se passe-t-il si un champ avec une contrainte de validation required: true est mis à jour pour être une chaîne vide ? Nous aurions besoin de cela pour déclencher une erreur de validation.

Cela m'intéresse aussi. Peut-être qu'un plug-in pourrait être écrit pour remplacer la méthode .update() et exécuter la validation ? De cette façon, même une solution partielle peut être mise en œuvre. Si c'était dans le noyau, en revanche, on s'attendrait à ce qu'il gère tous les types de validation et soit 100% robuste.

J'ai également rencontré cela, avec des validateurs personnalisés et des énumérations. Bien qu'il soit possible de rechercher puis de mettre à jour, cela rend très difficile l'écriture de code de cas général lorsque les documents ont des structures de sous-documents différentes.

+1 bosse ça.

La solution de Brian semble assez élégante. J'adorerais être averti lorsque les correctifs arrivent en version bêta.

+1

besoin de ça +1

+1

+1

+1

+1

Dans la version 3.9.3, update() aura 2 options spéciales, setDefaultsOnInsert et runValidators , qui définiront les valeurs par défaut et exécuteront des validateurs sur votre requête. Voir les tests par exemple, pas encore de vrais docs :(

Merci beaucoup - c'est une excellente solution !

@ vkarpov15 J'ai utilisé votre code pour appliquer également la validation à findOneAndUpdate. Voir RP #2393.

Bonjour, savez-vous quand sortira la version stable 3.9 afin d'utiliser la validation à la mise à jour ?

Merci

@AlexandreAWE bonne question. Je suis actuellement en train de terminer les choses sur 4.0 et de tester la version bêta de la branche 3.9.x, mais pour le moment, c'est une chose "ce sera fait quand ce sera fait". J'espère avoir un RC avant Noël.

@vkarpov15 Comment ça se passe sur l'écurie 3.9.x ? Ce serait formidable d'avoir des validations lors de la mise à jour au lieu de rechercher et d'enregistrer à chaque fois pour mon projet en cours.

@andrewholsted attend que le pilote mongodb 2.0 et le serveur mongodb 2.8 se stabilisent - cela se produira, espérons-le, ce mois-ci, mais ne peut pas vraiment être livré 4.0 sans prendre en charge la dernière version de mongodb et le dernier pilote. Voir mon blog pour un peu plus de détails.

Question potentiellement stupide de ma part, mais pourquoi ne pas prendre les données en cours de mise à jour et les valider par rapport au schéma avant de passer à mongodb ?

Aussi, +1

marquer et attendre

J'ai hâte que la 3.9 soit stable :)

Cette fonctionnalité est-elle déjà disponible ? J'attends avec impatience la 3.9.. Quand sera-t-elle disponible ?

Vous pouvez npm install mongoose@unstable pour obtenir la version instable. L'ETA actuel pour 4.0 est le 25 mars - un bon endroit pour vérifier c'est la page des jalons

Je viens de rencontrer ce problème hier soir. Content de ne pas être le seul ! Je suis ravi que ce changement soit publié, merci pour tout ce que vous faites !

+1

Je ne sais pas pourquoi ce problème est marqué comme fermé. J'y suis toujours confronté.

En fait, je ne suis pas sûr que cela fonctionne sur la validation enum pour findOneAndUpdate(), même avec runValidators défini sur true.

@m1cah s'il vous plaît fournir un exemple qui montre ce que vous essayez de faire. Nous avons des tests pour cela et ils réussissent...

@vkarpov15 Je crois que c'est un court exemple qui le démontre: http://code.runnable.com/VYhGbVhereIYdbst/update-validation-enum-for-mongoose-and-databases

Eh bien, un problème est que l'exemple ci-dessus utilise une version préhistorique de la mangouste :

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

Essayez de passer à 4.x et cela devrait fonctionner.

Êtes-vous sûr que cela fonctionne avec une méthode enum et findOneAndUpdate ?
Sur mongoose 4.2.6, cela semble échouer, je peux définir une mauvaise valeur.

Schéma :

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éthode FindOneAndUpdate :

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

Alors je peux pousser embededData.type = 'Panda';

Voir la documentation du validateur de mise à jour et #2933 - les validateurs de mise à jour ne s'exécutent pas sur $push , uniquement sur $set et $unset

+1

Autant que je sache, cela ne fonctionne toujours pas dans le cas où vous utilisez un validateur personnalisé sur un champ qui est un tableau.

Par exemple, cet extrait de code :

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

vous permettra de mettre à jour l'utilisateur pour qu'il ait un champ name de ["John"] sans générer d'erreurs, même si le validateur personnalisé que j'ai inclus interdit explicitement tout tableau de noms de longueur inférieure ou égale à 1. Le validator lui-même fonctionne très bien, comme on peut le voir par le fait que si vous décommentez la ligne console.log(data.validateSync()) , forçant ainsi la validation à avoir lieu, il renverra en fait le message d'erreur approprié. Le problème est que cette validation n'a pas lieu dans l'appel findOneAndUpdate() , malgré le fait que j'inclus l'option runValidators=true .

Cela ressemble à un bug, pouvez-vous ouvrir un problème séparé pour cela?

Merci

Existe-t-il un correctif disponible pour le problème ci-dessus ? @vkarpov15

@Saravanan90 s'il vous plaît arrêtez de commenter des problèmes fermés depuis longtemps sans aucune information significative. Ouvrez un problème distinct avec des exemples de code.

Cette page vous a été utile?
0 / 5 - 0 notes