虚拟填充猫鼬
Posted
技术标签:
【中文标题】虚拟填充猫鼬【英文标题】:Virtual populate mongoose 【发布时间】:2021-01-09 21:06:03 【问题描述】:我尝试在我创建的两个模型之间使用虚拟填充: 在这种情况下,获取带有游览 ID 的所有评论并与游览一起显示。 (当使用查询 findById() 仅显示此游览时)
我的虚拟在架构中设置为 true(我尝试在使用虚拟填充后将它们设置为 true,但它不起作用 - 通过 soultion)
在检查了 mongoose 文档后,它似乎是正确的,但它不起作用。
我的游览架构:
const tourSchema = new mongoose.Schema(
name:
type: String,
required: [true, 'A tour must have a name'], //validator
unique: true,
trim: true,
maxlength: [40, 'A tour name must have less or equal then 40 characters'],
minlength: [10, 'A tour name must have at least 10 character']
//validate: [validator.isAlpha, 'A tour name must have only alphabetic characters']
,
etc...
etc...
etc...
//guides: Array --- array of user id's || embedding
guides: [
//Reference to the user data model without saving the guides in the tour data model
//Child referencing
type: mongoose.Schema.ObjectId,
ref: 'User'
]
,
//passing options, getting the virual properties to the document/object
toJSON: virtuals: true ,
toObject: virtuals: true
);
//Define virtual properties
tourSchema.virtual('durationWeeks').get(function ()
console.log('Virtual 1');
//using function declaration => using this keyword
return this.duration / 7;
);
//Virtual populate
tourSchema.virtual('reviews',
ref: 'review',
localField: '_id', // Find tour where `localField`
foreignField: 'tour', // is equal to `foreignField`
//look for the _id of the tour in the tour field in review
);
我的评论架构: ** 我在巡演的审核模式中使用,并为巡演 ID 填充用户 **
const reviewSchema = new mongoose.Schema(
review:
type: String,
required: [true, 'Review can not be empty!']
,
rating:
type: Number,
min: 1,
max: 5
,
createdAt:
type: Date,
default: Date.now(),
,
tour: [
type: mongoose.Schema.ObjectId,
ref: 'Tour',
required: [true, 'Review must be belong to a tour.']
],
user: [
type: mongoose.Schema.ObjectId,
ref: 'User',
required: [true, 'Review must be belong to a user.']
]
,
//passing options, getting the virual properties to the document/object
toJSON: virtuals: true ,
toObject: virtuals: true ,
);
//Query middleware
reviewSchema.pre(/^find/, function (next)
this.populate(
path: 'tour',
select: 'name'
)
.populate(
path: 'user',
select: 'name'
);
next();
);
我的输出: 获取所有评论(查看模型数据):
"status": "success",
"data":
"review": [
"_id": "5f6ba5b45624454efca7e0b1",
"review": "What an amzing tour",
"tour":
"guides": [],
"_id": "5c88fa8cf4afda39709c2955",
"name": "The Sea Explorer",
"durationWeeks": null,
"id": "5c88fa8cf4afda39709c2955"
,
"user":
"_id": "5f69f736e6eb324decbc3a52",
"name": "Liav"
,
"createdAt": "2020-09-23T19:44:52.519Z",
"id": "5f6ba5b45624454efca7e0b1"
]
以及通过 id 获取游览:
"status": "success",
"data":
"tour":
"startLocation":
"type": "Point",
"coordinates": [
-80.185942,
25.774772
],
"description": "Miami, USA",
"address": "301 Biscayne Blvd, Miami, FL 33132, USA"
,
"ratingsAverage": 4.8,
"ratingsQuantaity": 0,
"images": [
"tour-2-1.jpg",
"tour-2-2.jpg",
"tour-2-3.jpg"
],
"startDates": [
"2021-06-19T09:00:00.000Z",
"2021-07-20T09:00:00.000Z",
"2021-08-18T09:00:00.000Z"
],
"secretTour": false,
"guides": [],
"_id": "5c88fa8cf4afda39709c2955",
.
.
.
.
"slug": "the-sea-explorer",
"__v": 0,
"durationWeeks": 1,
"id": "5c88fa8cf4afda39709c2955"
您可以看到评论将游览作为 arr 并且 id 在游览的 arr 内是否存在填充未针对正确字段的选项?
【问题讨论】:
【参考方案1】:所以我想通了。 首先我在 github - mongoose repo 中询问并得到了回答:
reviewSchema.pre(/^find/, function (next)
this.populate(
path: 'tour',
options: select: 'name' // <-- wrap `select` in `options` here...
).populate(
path: 'user',
options: select: 'name photo' // <-- and here
);
next();
);
我们应该改进这一点:嵌套选项非常令人困惑,而且 很难记住应该是 options.select 还是 select
第二个问题是在游览控制器中使用 FindById 方法后添加填充,使用填充而不使用包装“选择”对我不起作用。
exports.getTour = catchAsync(async (req, res, next) => //parameter => :id || optinal parameter => :id?
//populate reference to the guides in the user data model
const tour = await Tour.findById(req.params.id).populate('reviews');
if (!tour)
return next(new AppError('No tour found with that id', 404));
res.status(200).json(
status: 'success',
data:
tour
);
)
在游览模型中,我将外键从“tour_id”更改(正如我在其他问题中看到的那样)。
//Virtual populate
tourSchema.virtual('reviews',
ref: 'Review',
localField: '_id', // Find tour where `localField`
foreignField: 'tour' // is equal to `foreignField`
//look for the _id of the tour in the tour field in review
);
现在我的旅游数据中确实有评论,它确实通过 id 虚拟填充到旅游中
【讨论】:
【参考方案2】:您需要将选项virtuals: true
传递到架构创建中:
const tourSchema = new mongoose.Schema(
...
,
virtuals: true
此外,我们使用mongoose-lean-virtuals
模块来帮助处理 .lean 和 virtuals。例如
const mongooseLeanVirtuals = require('mongoose-lean-virtuals');
...
tourSchema.plugin(mongooseLeanVirtuals);
tourSchema.set('toJSON', virtuals: true );
tourSchema.set('toObject', virtuals: true );
虽然我猜这不是绝对必要的。
【讨论】:
嘿,那没用,在我的 tourSchema 中你也可以看到,在定义模型后将 virtuals 设置为 true。此外,我更新了问题并发布了我得到回复的 JSON。在 reviewSchema 中,我得到了游览的 id,但在游览对象的 arr 中,我可能无法正确填充来获取 id?以上是关于虚拟填充猫鼬的主要内容,如果未能解决你的问题,请参考以下文章