我正在尝试使用 mongoose 自动用另一个模型填充一个模型。 遵循此官方文档:https://mongoosejs.com/docs/populate.html
我无法使用标准引用:“ModelName”,因为只有当您使用 _id 字段作为关系字段时,它才有效...并且我有自己的关系链接字段,例如“itemId”和“subItemIs”,并且我无法使用“_id”字段
因此,我使用名为 Populate Virtuals 的子功能(此处的官方文档:https://mongoosejs.com/docs/populate.html#populate-virtuals)
虽然我可以使该功能在某些建模案例中完美工作......我拥有的特定模型案例是唯一一个我无法使其发挥作用的案例。
这是“一张图片胜过千言万语”的情况之一,因此与其描述问题,不如简单地阅读一个数据+代码片段,该片段公开了何时工作以及何时失败
我实际上创建了一个不言自明的孤立数据+代码,它完全描述了实现预期目标的需求和失败:
猫鼬版本:8.1.1 Node.js 版本:20.5.0 MongoDB服务器版本:7.0.4 Typescript 版本:未使用
// Mongo Data:
//
// Collection: units
// { unitId: 'in', label: 'Inches' }
// { unitId: 'ft', label: 'Feet' }
// { unitId: 'yr', label: 'Yard' }
//
// Collection: reports:
// {
// reportId: 'r1',
// singleMeasurement:
// { value: '1', unitId: 'in' },
// multipleMeasurements: [
// { value: '2', unitId: 'ft' },
// { value: '3', unitId: 'yr' }
// ]
// }
import mongoose from 'mongoose'
const unitSchema = new mongoose.Schema({
unitId: { type: String },
label: { type: String }
})
const reportSchema = new mongoose.Schema({
reportId: { type: String },
singleMeasurement: {
value: { type: Number },
unitId: { type: String } // This WORKS to assist creating 'unit' attribute in 'singleMeasurement' obj
},
multipleMeasurements: [{
value: { type: Number },
unitId: { type: String } // This FAILS to assist creating 'unit' attribute in 'multipleMeasurements' obj array
}]
})
reportSchema.virtual('singleMeasurement.unit', { ref: 'Unit', localField: 'singleMeasurement.unitId', foreignField: 'unitId' })
reportSchema.virtual('multipleMeasurements.unit', { ref: 'Unit', localField: 'multipleMeasurements.unitId', foreignField: 'unitId' })
reportSchema.set('toJSON', { virtuals: true })
reportSchema.set('toObject', { virtuals: true })
// // // // // // // // // // // // // // //
const reportModel = mongoose.model('Report', reportSchema, 'reports')
const unitModel = mongoose.model('Unit', unitSchema, 'units')
// // // // // // // // // // // // // // //
await mongoose.connect('mongodb://username:password@localhost:27017/database')
const report = await reportModel.findOne({ reportId: 'r1' })
await report.populate('singleMeasurement.unit')
await report.populate('multipleMeasurements.unit')
console.log('\n\n singleMeasurement: ' + report.singleMeasurement.toString())
// this WORKS; by including singleMeasurement.unit
console.log('\n\n multipleMeasurements: ' + report.multipleMeasurements.toString())
// this FAILS; by missing multipleMeasurements.unit
这些是预期结果和假设:
// report.singleMeasurement.unit => Expected: Object => Received: Object => OK
// report.multipleMeasurements[].unit => Expected: Object => Received: undefined => FAIL
我还尝试将 localField 更改为“multipleMeasurements.$*.unitId”,这是支持在地图内填充所需的语法......但它也不起作用。
是否可能还有另一种类似于该语法的语法,但对于我无法理解的数组?
执行此操作的最佳方法是创建一个
multipleMeasurement
模式并在该模式上注册虚拟。然后,您可以使用该架构作为 multipleMeasurements
数组的类型。这是一个例子:
multipleMeasurementSchema
const multipleMeasurementSchema = new mongoose.Schema({
value: {
type: Number
},
unitId: {
type: String
}
}, {
toJSON: {
virtuals: true
},
toObject: {
virtuals: true
}
});
multipleMeasurementSchema
multipleMeasurementSchema.virtual('unit', { ref: 'Unit', localField: 'unitId', foreignField: 'unitId' });
multipleMeasurementSchema
设置为 multipleMeasurements
数组类型const reportSchema = new mongoose.Schema({
reportId: { type: String },
singleMeasurement: {
value: { type: Number },
unitId: { type: String }
},
multipleMeasurements: [multipleMeasurementSchema]
})
singleMeasurement.unit
上注册虚拟reportSchema.virtual('singleMeasurement.unit', { ref: 'Unit', localField: 'singleMeasurement.unitId', foreignField: 'unitId' });
reportSchema.set('toJSON', { virtuals: true })
reportSchema.set('toObject', { virtuals: true })
populate
const report = await reportModel.findOne({ reportId: 'r1' })
.populate('singleMeasurement.unit')
.populate('multipleMeasurements.unit')