SchemaType.prototype.set()
Parameters
- fn «Function»
Returns:
- «SchemaType» this
Adds a setter to this schematype.
Example:
function capitalize (val) {
if (typeof val !== 'string') val = '';
return val.charAt(0).toUpperCase() + val.substring(1);
}
// defining within the schema
const s = new Schema({ name: { type: String, set: capitalize }});
// or with the SchemaType
const s = new Schema({ name: String })
s.path('name').set(capitalize);
Setters allow you to transform the data before it gets to the raw mongodb document or query.
Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account — e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.
You can set up email lower case normalization easily via a Mongoose setter.
function toLower(v) {
return v.toLowerCase();
}
const UserSchema = new Schema({
email: { type: String, set: toLower }
});
const User = db.model('User', UserSchema);
const user = new User({email: 'AVENUE@Q.COM'});
console.log(user.email); // 'avenue@q.com'
// or
const user = new User();
user.email = 'Avenue@Q.com';
console.log(user.email); // 'avenue@q.com'
User.updateOne({ _id: _id }, { $set: { email: 'AVENUE@Q.COM' } }); // update to 'avenue@q.com'
As you can see above, setters allow you to transform the data before it stored in MongoDB, or before executing a query.
NOTE: we could have also just used the built-in lowercase: true
SchemaType option instead of defining our own function.
new Schema({ email: { type: String, lowercase: true }})
Setters are also passed a second argument, the schematype on which the setter was defined. This allows for tailored behavior based on options passed in the schema.
function inspector (val, schematype) {
if (schematype.options.required) {
return schematype.path + ' is required';
} else {
return val;
}
}
const VirusSchema = new Schema({
name: { type: String, required: true, set: inspector },
taxonomy: { type: String, set: inspector }
})
const Virus = db.model('Virus', VirusSchema);
const v = new Virus({ name: 'Parvoviridae', taxonomy: 'Parvovirinae' });
console.log(v.name); // name is required
console.log(v.taxonomy); // Parvovirinae
You can also use setters to modify other properties on the document. If you’re setting a property name
on a document, the setter will run with this
as the document. Be careful, in mongoose 5 setters will also run when querying by name
with this
as the query.
const nameSchema = new Schema({ name: String, keywords: [String] });
nameSchema.path('name').set(function(v) {
// Need to check if `this` is a document, because in mongoose 5
// setters will also run on queries, in which case `this` will be a
// mongoose query object.
if (this instanceof Document && v != null) {
this.keywords = v.split(' ');
}
return v;
});