您似乎想要在这里简单地设置一个带有“别名”名称的“虚拟”字段。这允许您为字段使用不同的名称,但这些名称将“重新映射”到架构中定义的正确名称。
作为一个完整的演示:
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() 函数用于在您实际请求addr 时从address 读取,而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 Schema 文档中