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.