Categories
MongoDB

Using MongoDB with Mongoose — Validators on Nested Objects and Updates

Spread the love

To make MongoDB database manipulation easy, we can use the Mongoose NPM package to make working with MongoDB databases easier.

In this article, we’ll look at how to use Mongoose to manipulate our MongoDB database.

Required Validators on Nested Objects

We can define validators on nested objects with Mongoose.

To do that, we can write:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const nameSchema = new Schema({
    first: String,
    last: String
  });

  const personSchema = new Schema({
    name: {
      type: nameSchema,
      required: true
    }
  });

  const Person = connection.model('Person', personSchema);
  const doc = new Person({});
  const err = doc.validateSync();
  console.log(err);
}
run();

We created the nameSchema which is embedded in the personSchema so that we can require both the name.first and name.last nested fields.

Now when we create a new Person instance, we’ll see an error because we haven’t added those properties into our document.

Update Validators

Mongoose also supports validation for updating documents with the update , updateOne , updateMany , and findOneAndUpdate methods.

Update validators are off by default. We need the runValidators option to turn it on.

For example, we can write:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const toySchema = new Schema({
    color: String,
    name: String
  });
  const Toy = connection.model('Toys', toySchema);
  Toy.schema.path('color').validate(function (value) {
    return /red|green|blue/i.test(value);
  }, 'Invalid color');

  const opts = { runValidators: true };
  Toy.updateOne({}, { color: 'not a color' }, opts, (err) => {
    console.log(err.errors.color.message);
  });
}
run();

Since we have the runValidators property set to true in the opts object, we’ll get validator when we call the updateOne method.

Then we should see the ‘Invalid color’ message logged in the console log in the callback.

Update Validators and this

The value of this for update validators and document validators.

In document validators, this refers to the document itself.

However, when we’re updating a document, the document that’s updated may not be in memory itself.

Therefore, this is not defined by default.

The context optioin lets us set the value of this in update validators.

For example, we can write:

const { captureRejectionSymbol } = require('events');

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const toySchema = new Schema({
    color: String,
    name: String
  });
  toySchema.path('color').validate(function (value) {
    if (this.getUpdate().$set.name.toLowerCase().indexOf('red') !== -1) {
      return value === 'red';
    }
    return true;
  });

  const Toy = connection.model('Toy', toySchema);
  const update = { color: 'blue', name: 'red car' };
  const opts = { runValidators: true, context: 'query' };
  Toy.updateOne({}, update, opts, (error) => {
    console.log(error.errors['color']);
  });
}
run();

to set the context property in the opts object to 'query' to make this defined in the validator when we do updates.

Conclusion

We can add validators to updates operations in Mongoose. It’s not enabled by default.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *