使用 virtual 属性 访问 Mongoose 模型中的嵌套文档
Use virtual property to access nested document in Mongoose model
我正在尝试在我的一个模式中创建一个虚拟项目,这将需要访问该模式中引用的项目所引用的数据(是的,那是 2 个深度引用,连接 3 个 schemas/models)
我在这里尝试尽可能接近地模拟代码,使用 Model/Schema A/B/C..
这将是 ModelA 的架构,其中包含依赖于引用的虚拟项目:
// models/modela.js
// SchemaA for ModelA
const SchemaA = new Schema({
_foo: {
// References ModelB
type: Schema.Types.ObjectId,
ref: 'ModelB'
}
})
// Virtual `Modela.something`, which needs the data from ModelC.baz
SchemaA.virtual('something').get(function () {
// How can I access ModelC.baz
return 'Value from ModelC'
});
然后是 ModelB 的架构:
// models/modelb.js
// SchemaB for ModelB
const SchemaB = new Schema({
_bar: [{
// References ModelC.baz
type: Schema.Types.ObjectId,
ref: 'ModelC'
}]
})
以及 ModelC 的架构:
// models/modelc.js
// SchemaC for ModelC
const SchemaC = new Schema({
baz: Schema.Types.String
})
正如您在上面看到的,我需要做的是从 中的虚拟 something
项目中访问 Modelc.haz模型A
我认为,如果我通过查询本身对两个群体都进行了处理,那么也许这会奏效,所以我尝试了类似的方法:
this.find()
.populate( '_foo' )
.populate( '_foo._bar' )
哪个没用(实际上我真的没想到,但是哦好吧)
可以使用Model.populate方法实现:
ModelA
.find()
.populate({
path: '_foo'
})
.exec(function(err, docs) {
if (err) throw err;
// Populate the '_bar' array of the '_foo' property which is
// an instance of ModelB
ModelB.populate(docs[0]._foo, { path: '_bar' }, function(err, result) {
console.log('Showing ModelC.baz:', docs[0].something);
});
});
您可以这样定义虚拟 属性:
SchemaA.virtual('something').get(function () {
// How can I access ModelC.baz
return this._foo._bar[0].baz;
});
您可以在 this github issue 找到更多相关信息。您可以使用查询挂钩。
我有类似的问题,所以我用它来填充参考模型以在虚函数中使用。这是一个示例。
const tutorialSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
videos: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Video'
}
]
});
tutorialSchema.pre('findOne', function (next) {
this.populate('videos'); // now can be accessed using this.videos
next();
});
tutorialSchema.virtual('totalTime').get(function () {
let times = [];
times = this.videos.map((v) => {
return v.duration;
});
if(times.length === 0) return 0;
let totalTime; // find total time of videos and then return
return totalTime;
});
我正在尝试在我的一个模式中创建一个虚拟项目,这将需要访问该模式中引用的项目所引用的数据(是的,那是 2 个深度引用,连接 3 个 schemas/models)
我在这里尝试尽可能接近地模拟代码,使用 Model/Schema A/B/C..
这将是 ModelA 的架构,其中包含依赖于引用的虚拟项目:
// models/modela.js
// SchemaA for ModelA
const SchemaA = new Schema({
_foo: {
// References ModelB
type: Schema.Types.ObjectId,
ref: 'ModelB'
}
})
// Virtual `Modela.something`, which needs the data from ModelC.baz
SchemaA.virtual('something').get(function () {
// How can I access ModelC.baz
return 'Value from ModelC'
});
然后是 ModelB 的架构:
// models/modelb.js
// SchemaB for ModelB
const SchemaB = new Schema({
_bar: [{
// References ModelC.baz
type: Schema.Types.ObjectId,
ref: 'ModelC'
}]
})
以及 ModelC 的架构:
// models/modelc.js
// SchemaC for ModelC
const SchemaC = new Schema({
baz: Schema.Types.String
})
正如您在上面看到的,我需要做的是从 中的虚拟 something
项目中访问 Modelc.haz模型A
我认为,如果我通过查询本身对两个群体都进行了处理,那么也许这会奏效,所以我尝试了类似的方法:
this.find()
.populate( '_foo' )
.populate( '_foo._bar' )
哪个没用(实际上我真的没想到,但是哦好吧)
可以使用Model.populate方法实现:
ModelA
.find()
.populate({
path: '_foo'
})
.exec(function(err, docs) {
if (err) throw err;
// Populate the '_bar' array of the '_foo' property which is
// an instance of ModelB
ModelB.populate(docs[0]._foo, { path: '_bar' }, function(err, result) {
console.log('Showing ModelC.baz:', docs[0].something);
});
});
您可以这样定义虚拟 属性:
SchemaA.virtual('something').get(function () {
// How can I access ModelC.baz
return this._foo._bar[0].baz;
});
您可以在 this github issue 找到更多相关信息。您可以使用查询挂钩。
我有类似的问题,所以我用它来填充参考模型以在虚函数中使用。这是一个示例。
const tutorialSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
videos: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Video'
}
]
});
tutorialSchema.pre('findOne', function (next) {
this.populate('videos'); // now can be accessed using this.videos
next();
});
tutorialSchema.virtual('totalTime').get(function () {
let times = [];
times = this.videos.map((v) => {
return v.duration;
});
if(times.length === 0) return 0;
let totalTime; // find total time of videos and then return
return totalTime;
});