Получатели/установщики в Mongoose
Получатели и установщики Mongoose позволяют вам выполнять пользовательскую логику при получении или установке свойства в документе Mongoose. Получатели позволяют преобразовывать данные из MongoDB в более удобную для пользователя форму, а установщики позволяют преобразовывать данные пользователя перед их отправкой в MongoDB.
Получатели
Предположим, у вас есть коллекция User и вы хотите замаскировать электронные адреса пользователей, чтобы защитить их конфиденциальность. Ниже приведен базовый userSchema для маскирования электронного адреса пользователя.
const userSchema = new Schema({
email: {
type: String,
get: obfuscate
}
});
// Mongoose passes the raw value in MongoDB `email` to the getter
function obfuscate(email) {
const separatorIndex = email.indexOf('@');
if (separatorIndex < 3) {
// 'ab@gmail.com' -> '**@gmail.com'
return email.slice(0, separatorIndex).replace(/./g, '*') +
email.slice(separatorIndex);
}
// 'test42@gmail.com' -> 'te****@gmail.com'
return email.slice(0, 2) +
email.slice(2, separatorIndex).replace(/./g, '*') +
email.slice(separatorIndex);
}
const User = mongoose.model('User', userSchema);
const user = new User({ email: 'ab@gmail.com' });
user.email; // **@gmail.com
Помните, что получатели не влияют на данные, хранящиеся в MongoDB. Если вы сохраните user, свойство email будет 'ab@gmail.com' в базе данных.
По умолчанию Mongoose не выполняет получатели при преобразовании документа в JSON, включая функцию Express res.json().
app.get(function(req, res) {
return User.findOne().
// The `email` getter will NOT run here
then(doc => res.json(doc)).
catch(err => res.status(500).json({ message: err.message }));
});
Чтобы запустить получатели при преобразовании документа в JSON, установите опцию toJSON.getters в true в вашей схеме, как показано ниже.
const userSchema = new Schema({
email: {
type: String,
get: obfuscate
}
}, { toJSON: { getters: true } });
// Or, globally
mongoose.set('toJSON', { getters: true });
// Or, on a one-off basis
app.get(function(req, res) {
return User.findOne().
// The `email` getter will run here
then(doc => res.json(doc.toJSON({ getters: true }))).
catch(err => res.status(500).json({ message: err.message }));
});
Чтобы пропустить получатели в одноразовом режиме, используйте user.get() с опцией getters установленной в false, как показано ниже.
user.get('email', null, { getters: false }); // 'ab@gmail.com'
Установщики
Предположим, вы хотите убедиться, что все электронные адреса пользователей в вашей базе данных приведены к нижнему регистру, чтобы упростить поиск без учета регистра. Ниже приведен пример userSchema , который гарантирует, что электронные адреса приведены к нижнему регистру.
const userSchema = new Schema({
email: {
type: String,
set: v => v.toLowerCase()
}
});
const User = mongoose.model('User', userSchema);
const user = new User({ email: 'TEST@gmail.com' });
user.email; // 'test@gmail.com'
// The raw value of `email` is lowercased
user.get('email', null, { getters: false }); // 'test@gmail.com'
user.set({ email: 'NEW@gmail.com' });
user.email; // 'new@gmail.com'
Mongoose также выполняет установщики при операциях обновления, таких как updateOne(). Mongoose будет обновлять документ с электронным адресом в нижнем регистре в приведенном ниже примере.
await User.updateOne({}, { email: 'TEST@gmail.com' }, { upsert: true });
const doc = await User.findOne();
doc.email; // 'test@gmail.com'
В функции установщика this может быть либо документ, который устанавливается, либо запрос, который выполняется. Если вы не хотите, чтобы ваш установщик выполнялся при вызове updateOne(), добавьте инструкцию if, которая проверяет, является ли this документом Mongoose, как показано ниже.
const userSchema = new Schema({
email: {
type: String,
set: toLower
}
});
function toLower(email) {
// Don't transform `email` if using `updateOne()` or `updateMany()`
if (!(this instanceof mongoose.Document)) {
return email;
}
return email.toLowerCase();
}
const User = mongoose.model('User', userSchema);
await User.updateOne({}, { email: 'TEST@gmail.com' }, { upsert: true });
const doc = await User.findOne();
doc.email; // 'TEST@gmail.com'
Передача параметров с помощью $locals
Вы не можете передавать параметры в свои функции получения и установки, как вы это делаете в обычных вызовах функций. Чтобы настроить или передать дополнительные свойства своим получателям и установщикам, вы можете использовать свойство $locals документа.
Свойство $locals является предпочтительным местом для хранения любых данных, определенных программой, в вашем документе без конфликтов со свойствами, определенными схемой. В ваших функциях получения и установки this является документом, к которому осуществляется доступ, поэтому вы устанавливаете свойства на $locals , а затем получаете доступ к этим свойствам в ваших примерах получателей. Например, следующее показывает, как вы можете использовать $locals для настройки языка для пользовательского получателя, возвращающего строку на разных языках.
const internationalizedStringSchema = new Schema({
en: String,
es: String
});
const ingredientSchema = new Schema({
// Instead of setting `name` to just a string, set `name` to a map
// of language codes to strings.
name: {
type: internationalizedStringSchema,
// When you access `name`, pull the document's locale
get: function(value) {
return value[this.$locals.language || 'en'];
}
}
});
const recipeSchema = new Schema({
ingredients: [{ type: mongoose.ObjectId, ref: 'Ingredient' }]
});
const Ingredient = mongoose.model('Ingredient', ingredientSchema);
const Recipe = mongoose.model('Recipe', recipeSchema);
// Create some sample data
const { _id } = await Ingredient.create({
name: {
en: 'Eggs',
es: 'Huevos'
}
});
await Recipe.create({ ingredients: [_id] });
// Populate with setting `$locals.language` for internationalization
const language = 'es';
const recipes = await Recipe.find().populate({
path: 'ingredients',
transform: function(doc) {
doc.$locals.language = language;
return doc;
}
});
// Gets the ingredient's name in Spanish `name.es`
assert.equal(recipes[0].ingredients[0].name, 'Huevos'); // 'Huevos'
Отличия от получателей/установщиков ES6
Установщики Mongoose отличаются от установщиков ES6, потому что они позволяют преобразовывать устанавливаемое значение. С установщиками ES6 вам нужно было бы сохранить внутреннее свойство _email , чтобы использовать установщик. С Mongoose вам не нужно определять внутреннее свойство _email или определять соответствующий получатель для email.
class User {
// This won't convert the email to lowercase! That's because `email`
// is just a setter, the actual `email` property doesn't store any data.
// also eslint will warn about using "return" on a setter
set email(v) {
// eslint-disable-next-line no-setter-return
return v.toLowerCase();
}
}
const user = new User();
user.email = 'TEST@gmail.com';
user.email; // undefined
© 2010 LearnBoost
Licensed under the MIT License.
https://mongoosejs.com/docs/tutorials/getters-setters.html