question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Mongoose findOneAndUpdate and runValidators not working

See original GitHub issue

I am having issues trying to get the ‘runValidators’ option to work. My user schema has an email field that has required set to true but each time a new user gets added to the database (using the ‘upsert’ option) and the email field is empty it does not complain:

 var userSchema = new mongoose.Schema({
   facebookId: {type: Number, required: true},
   activated: {type: Boolean, required: true, default: false},
   email: {type: String, required: true}
});

findOneAndUpdate code:

model.user.user.findOneAndUpdate(
      {facebookId: request.params.facebookId},
      {
          $setOnInsert: {
              facebookId: request.params.facebookId,
              email: request.payload.email,
          }
      },
      {upsert: true, 
       new: true, 
       runValidators: true, 
       setDefaultsOnInsert: true
      }, function (err, user) {
          if (err) {
              console.log(err);
              return reply(boom.badRequest(authError));
          }
          return reply(user);
      });

I have no idea what I am doing wrong, I just followed the docs: http://mongoosejs.com/docs/validation.html

In the docs is says the following:

Note that in mongoose 4.x, update validators only run on $set and $unset operations. For instance, the below update will succeed, regardless of the value of number.

I replaced the $setOnInsert with $set but had the same result.

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:9 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
vkarpov15commented, Jul 11, 2015

So the below script:

var assert = require('assert');
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.set('debug', true);
mongoose.connect('mongodb://localhost:27017/gh3124');

var userSchema = new mongoose.Schema({
   facebookId: {type: Number, required: true},
   activated: {type: Boolean, required: true, default: false},
   email: {type: String, required: true}
});

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

User.findOneAndUpdate(
  {facebookId: 123},
  {
    $setOnInsert: {
      facebookId: 123,
      email: undefined,
    }
  },
  {upsert: true,     
   'new': true,   
   runValidators: true,     
   setDefaultsOnInsert: true
  }, function (err, user) {
    console.log(err);
    process.exit(0);
  });

Gives me a validation error as expected in 4.0.6. Can you run that script locally and double check that it works for you @Jdruwe ?

1reaction
jeremymlcommented, Mar 15, 2016

I created a plugin to validate required model properties before doing update operations in mongoose.

var mongoose = require('mongoose');
var _ = require('lodash');
var s = require('underscore.string');

function validateExtra(schema, options){
    schema.methods.validateRequired = function(){
        var deferred = Promise.defer();
        var self = this;
        try {
            _.forEach(this.schema.paths, function (val, key) {
                if (val.isRequired && _.isUndefined(self[key])) {
                    throw new Error(s.humanize(key) + ' is not set and is required');
                }
            });
            deferred.resolve();
        } catch (err){
            deferred.reject(err);
        }
        return deferred.promise;
    }
}

module.exports = validateExtra;

Must be called explicitly as a method from the model, so I recommend chaining it a .then chain prior to the update call.

fuelOrderModel(postVars.fuelOrder).validateRequired()
        .then(function(){
            return fuelOrderModel.findOneAndUpdate({_id: postVars.fuelOrder.fuelOrderId}, postVars.fuelOrder,
                {runValidators: true, upsert: true, setDefaultsOnInsert: true, new: true})
                    .then(function(doc) {
                        res.json({fuelOrderId: postVars.fuelOrder.fuelOrderId});
                    });
        }, function(err){
                global.saveError(err, 'server', req.user);
                res.status(500).json(err);
        });
Read more comments on GitHub >

github_iconTop Results From Across the Web

Mongoose findOneAndUpdate and runValidators not working
In the docs is says the following: Note that in mongoose 4.x, update validators only run on $set and $unset operations. For instance,...
Read more >
Mongoose findOneAndUpdate and runValidators not working
I am having issues trying to get the 'runValidators' option to work. My post schema has an comments.replies.creator field that has required ...
Read more >
Mongoose v6.8.2: Validation
To turn on update validators, set the runValidators option for update() , updateOne() , updateMany() , or findOneAndUpdate() . Be careful: update validators...
Read more >
[Solved]-mongoose upsert not working-mongodb
Coding example for the question mongoose upsert not working-mongodb. ... var Hosts = mongoose.model('Hosts', new Schema({ address: String, model: String } ...
Read more >
Node.js – Mongoose findOneAndUpdate and runValidators not ...
I am having issues trying to get the 'runValidators' option to work. My user schema has an email field that has required set...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found