То, что вам здесь нужно, это просто установить «виртуальное» поле с именем «псевдоним».Это позволяет вам использовать разные имена для поля, но они будут «переназначаться» на правильное имя, как определено в схеме.
В качестве полной демонстрации:
const { Schema } = mongoose = require('mongoose');
const uri = 'mongodb://localhost/test';
mongoose.Promise = global.Promise;
mongoose.set('debug', true);
const addressSchema = new Schema({
address: { type: String, required: true }
});
// asssign a virtual to the "mapped" name
addressSchema.virtual('addr')
.get(function() { return this.address })
.set(function(v) { this.address = v });
const Address = mongoose.model('Adddress', addressSchema);
const log = data => console.log(JSON.stringify(data, undefined, 2));
(async function() {
try {
const conn = await mongoose.connect(uri);
await Promise.all(Object.entries(conn.models).map(([k,m]) => m.remove()));
// Raw documents don't work as the setter is ignored
try {
await Address.insertMany(
[{ adddress: "123 abc st" },{ addr: "123 abc st" }]
);
} catch(e) {
console.error(e);
}
// Creating via new works as expected
let doc = new Address({ addr: "123 abc st" });
log(doc);
// Using Array.map over the objects to cast them works fine
await Address.insertMany(
[{ address: "123 abc str" },{ addr: "245 abc st" }]
.map(Address)
);
let inserted = await Address.find();
log({ inserted });
mongoose.disconnect();
} catch (e) {
console.error(e)
} finally {
process.exit()
}
})();
Что демонстрируетожидаемые результаты:
Mongoose: adddresses.remove({}, {})
{ ValidationError: Adddress validation failed: address: Path `address` is required.
at ValidationError.inspect (/home/neillunn/projects/alias/node_modules/mongoose/lib/error/validation.js:56:24)
at formatValue (util.js:430:38)
at inspect (util.js:324:10)
at format (util.js:191:12)
at Console.warn (console.js:145:21)
at /home/neillunn/projects/alias/index.js:37:15
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
errors:
{ address:
{ ValidatorError: Path `address` is required.
at new ValidatorError (/home/neillunn/projects/alias/node_modules/mongoose/lib/error/validator.js:25:11)
at validate (/home/neillunn/projects/alias/node_modules/mongoose/lib/schematype.js:805:13)
at /home/neillunn/projects/alias/node_modules/mongoose/lib/schematype.js:854:11
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (/home/neillunn/projects/alias/node_modules/mongoose/lib/schematype.js:814:19)
at /home/neillunn/projects/alias/node_modules/mongoose/lib/document.js:1712:9
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
message: 'Path `address` is required.',
name: 'ValidatorError',
properties: [Object],
kind: 'required',
path: 'address',
value: undefined,
reason: undefined,
'$isValidatorError': true } },
_message: 'Adddress validation failed',
name: 'ValidationError' }
{
"_id": "5b110aa571311d0a70cd3c88",
"address": "123 abc st"
}
Mongoose: adddresses.insertMany([ { _id: 5b110aa571311d0a70cd3c89, address: '123 abc str', __v: 0 }, { _id: 5b110aa571311d0a70cd3c8a, address: '245 abc st', __v: 0 } ], {})
Mongoose: adddresses.find({}, { fields: {} })
{
"inserted": [
{
"_id": "5b110aa571311d0a70cd3c89",
"address": "123 abc str",
"__v": 0
},
{
"_id": "5b110aa571311d0a70cd3c8a",
"address": "245 abc st",
"__v": 0
}
]
}
Чтобы пройти через это, все, что определено в дополнение к полю adddress
в схеме, устанавливает другое виртуальное свойство в схеме:
addressSchema.virtual('addr')
.get(function() { return this.address })
.set(function(v) { this.address = v });
Это должно быть довольно просто, поскольку функция get()
используется для чтения из address
всякий раз, когда вы вместо этого фактически запрашиваете addr
, а функция set()
, конечно, применяется всякий раз, когда что-то пытается предоставить значение для addr
и затем вместо этого помещает это значение в adddress
.
Единственный улов в том, что эти "виртуалы" не применяются автоматически "везде", вы можете попытаться использовать их.Они работают находят с new Model()
, но они не применяются автоматически ни к Model.create()
, ни к Model.insertMany()
.
. В этом случае общий обходной путь, как показано ниже, это когда у вас есть список необработанных входных документов ".приведите «их», сначала запустив их через конструктор модели, как показано в листинге:
// Using Array.map over the objects to cast them works fine
await Address.insertMany(
[{ address: "123 abc str" },{ addr: "245 abc st" }]
.map(Address)
);
Затем данные будут правильно переписаны в address
в обоих документах, которые будут вставлены, и этопроисходит до того, как сработает валидатор required
.
В качестве альтернативы можно использовать свойство alias
в схеме:
const addressSchema = new Schema({
address: { type: String, required: true, alias: 'addr' }
});
Это на самом деле работает точно так же, без необходимостинаписать полный "виртуальный" методы.Вы можете считать это более коротким вариантом для выполнения того же действия, но вы, вероятно, должны знать, что на самом деле целью является «обратный», когда вы должны были определить «более короткое» имя в схеме и использовать «более длинное».для назначений.
Также вы можете добавить столько «виртуалов», сколько пожелаете, но вы можете использовать назначение alias
«один раз» в определении схемы.Так что, если у вас разные источники данных, которые используют разные имена для хранения того, что вы хотите, то, вероятно, лучше использовать более длинную форму.
Оба документа описаны в документации по схеме Mongoose