10

I am using express-validator for validation. I am using mongoose for database, it also has validation built in. I want to know which one should I use?

I also want to know if the validation in express-validator is parallel. Take this code for example:

req.checkBody('email', 'Invalid email').notEmpty().isEmail().isUnique();
req.checkBody('password', 'Invalid possword').notEmpty().len(8, 30);
req.checkBody('first_name', 'Invalid first_name').notEmpty().isAlpha();
req.checkBody('last_name', 'Invalid last_name').notEmpty().isAlpha();
req.checkBody('dateofbirth', 'Invalid dateofbirth').notEmpty.isDate();

isUnique() is a custom validation method that checks if the email has not already been registered or not, it queries to database to validate so. Though not mentioned in the code above but I also have few other post request where I need to validate multiple fields where database queries will be made in each of them.

So I wanted to know if its possible to run each of the above check method in parallel as that would make it faster and would also me more node like. I obviously will like to use a module for running these in parallel like async. I would also like to know if already these check methods are running in parallel already?

Please help me figure this out? Thanks in advance.

gustavohenke
  • 40,997
  • 14
  • 121
  • 129
Saransh Mohapatra
  • 9,430
  • 10
  • 39
  • 50

3 Answers3

10

express-validator is meant to validate input passed by the browser/client; Mongoose's validation is meant to validate newly created documents. Both serve a different purpose, so there isn't a clean-cut answer to which one you should use; you could use both, even.

As for the order of validation: the checks will be performed in series. You could use async.parallel() to make it appear as if the checks are performed in parallel, but in reality they won't be since the checks are synchronous.

EDIT: node-validator (and therefore express-validator) is a string validator. Testing for uniqueness isn't a string operation but operates on your data model, so you shouldn't try to use node-validator for it (in fact, I don't even think you can).

Instead, I would suggest using Mongoose's unique feature to ensure that an e-mail address only occurs once in your database.

Alternatively, use a validator module that supports async operations, like async-validate.

robertklep
  • 198,204
  • 35
  • 394
  • 381
  • Why I can't make them work in parallel? I mean if do it async.parallel(), then why will it still be synchronous? It seems to me they are functions which create a error which we check after these validations are done. If I am correct then we can use the parallel and check for error after all validations are done. Please clarify me the probs – Saransh Mohapatra Jul 13 '13 at 14:32
  • `async.parallel` will only parallelize asynchronous calls (I/O), which the Express-validator-calls aren't. Check out [the relevant documentation](https://github.com/ctavan/express-validator#validation-errors) on how you can handle errors (which is *also* done after all validations are done). – robertklep Jul 13 '13 at 15:18
  • Is this a problem with express-validator or node-validator? If its node-validator than I think its very difficult to fix it? But if its with express-validator than I hope something can be done. – Saransh Mohapatra Jul 13 '13 at 15:29
  • What 'problem' are you referring to? What should be fixed? – robertklep Jul 13 '13 at 15:36
  • You said that express-validator-calls are not asynchronous. So is it the express-validator or node-validator whose calls are not asynchronous? – Saransh Mohapatra Jul 13 '13 at 15:47
  • Both. But why is those calls not being asynchronous a problem? I'm confused as to why you need them to be asynchronous. – robertklep Jul 13 '13 at 15:51
  • You only said that as they are not asynchronous so these calls can't be run in parallel. I basically have to checkBody for many fields and wanted these checks to be in parallel. If you want to know why in parallel than its coz some of my validations need to do database queries and therefore running them in parallel would be faster. – Saransh Mohapatra Jul 13 '13 at 16:04
  • req.checkBody('email'{notEmpty:'Required',isEmail:'Invalid'}).notEmpty().isEmail(); req.checkBody('password', {notEmpty: 'Required'}).notEmpty(); req.checkBody('first_name').notEmpty(); req.checkBody('last_name').notEmpty(); Just to clarify I want each of these validations to be in parallel. – Saransh Mohapatra Jul 13 '13 at 16:07
  • Perhaps it would be better that you augment your question to explain exactly what you want. All the checks you mention (`notEmpty`, `isEmail`) are just simple checks, I don't see how they perform database queries (or could be made to perform them). – robertklep Jul 13 '13 at 16:47
  • I agree that I hadn't mentioned it. But basically I wanted to know is how to make those checks in parallel, not the database part so why would I mention that? – Saransh Mohapatra Jul 13 '13 at 16:59
  • You asked why I need that to be in parallel so I mentioned the database queries thing. Lets say for example I required that email to be unique and wrote a custom validator to check whether this email is unique or not? So now can you please help me out how to check all these in parallel. – Saransh Mohapatra Jul 13 '13 at 17:02
  • I have edited the question with the changes that were required. Please help me out. – Saransh Mohapatra Jul 13 '13 at 17:20
  • Are you suggesting that validation being asynchronous is bad? I would like to validate using mongoose but the problem is want the validation to not be in database level as some of my validation is more to do with how the app should be(though it uses database for validation). Do you think mongoose validation should be what I adopt? – Saransh Mohapatra Jul 14 '13 at 06:35
  • @SaranshMohapatra I think you should use a validation framework with support for asynchronous operation (which both `express-validator` and `node-validator` don't). There's nothing wrong with async validation as-is, just use the right tools :) – robertklep Jul 14 '13 at 07:58
  • @SaranshMohapatra I mentioned [`async-validate`](https://npmjs.org/package/async-validate). – robertklep Jul 14 '13 at 16:36
6

Using both mongodb unique constraint and express-validator will cause a little bit complicated errors processing: you need to analyse errors in different places and translate it to common format for rest response. So another approach will be creating custom express validator which will find record with such value in mongodb:

router.use(expressValidator({
    customValidators: {
      isUsernameAvailable(username) {
        return new Promise((resolve, reject) => {
          User.findOne({ username: username }, (err, user) => {
            if (err) throw err;
            if(user == null) {
              resolve();
            } else {
              reject();
            }
          });
        });
      }
    }
  })
);

...
req.checkBody('username', 'Username is required').notEmpty();
req.checkBody('username', 'Username already in use').isUsernameAvailable();


req.asyncValidationErrors().then(() => {
...

If you need, see total example with this code on my website: https://maketips.net/tip/161/validate-username-available-using-express-validator

Conclusion: express-validator supports asynchronous validation as well so you can perform any data and string validation you need without mixing user validation and low-level db backend validation

Make Tips
  • 180
  • 2
  • 6
0

There is no way that Express-Validator can check a email address is unique or not, on the other hand MongoDB is not responsible for checking your entered email address is in correct format.

So you must have to use both of them when they are in need because they serve completly diffrent purpose.

Rafiq
  • 8,987
  • 4
  • 35
  • 35