我尝试在创建的两个模型之间使用虚拟填充: 在这种情况下,将获得所有具有游览ID的评论,并在游览中显示它们。 (当使用查询findById()仅显示此游览时)
我的虚拟机在架构中设置为true(我尝试在使用虚拟填充器后将其设置为true,但此方法无效-通过soultion)
在检查过猫鼬的文档后,它似乎是正确的,但它不起作用。
我的tourSchema:
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内,是否存在填充对象未定位到正确字段的选项?
答案 0 :(得分:0)
您需要将一个选项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 });
尽管我猜想这不是绝对必要的。
答案 1 :(得分:0)
所以我知道了。 首先我在github中问-猫鼬回购并得到了答复:
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();
});
我们应该改善这一点:嵌套选项非常令人困惑,而且 很难记住是否应该选择某些东西。选择或选择
第二个问题是在巡回控制器中使用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”(在其他问题中看到的更改为“ tour”)。
//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将虚拟填充到巡回赛中