I\'ve searched about this issue and all the solutions that I\'ve found didn\'t actually work. I\'m currently using this function to encrypt the password before storing in th
user.pre('findOneAndUpdate', function(next){
    const user=this.getUpdate().$set;
    if(!user.password){
      next();
    }
    else{
    bcrypt.genSalt(10, function (err, salt) {
        if (err) {
          return next(err);
        }
        bcrypt.hash(user.password, salt, null, function (err, hash) {
          if (err) {
            return next(err);
          }
          user.password = hash;
           next();
        });
    });
  }
})
                                                                        I just tested this locally with:
var result = Author.findOneAndUpdate({ _id: <some id> }, { password: '111' }).exec()
and this pre hook:
AuthorSchema.pre('findOneAndUpdate', function(next) {
  this._update.password = 'BBB'
  next();
});
Password was saved as BBB
Author schema has a password field which is type: String
I am on 3.6.5
In your bcrypt case you have also an extra next() without else which is messing you up ... should be:
UserSchema.pre('findOneAndUpdate', function(next) {
  const update = this.getUpdate();
  if (!_.isEmpty(update.password)) {
    bcrypt.genSalt(10, (err, salt) => {
      bcrypt.hash(update.password, salt, (err, hash) => {
        this.getUpdate().password = hash;
        next();
      })
    })
  } else {
    next();
  }
});