首页 > 解决方案 > 虚拟填充猫鼬

问题描述

我尝试在我创建的两个模型之间使用虚拟填充:在这种情况下,获取所有带有游览 ID 的评论并通过游览显示它们。(当使用查询 findById() 仅显示此游览时)

我的虚拟在架构中设置为真(我尝试在使用虚拟填充后将它们设置为真,但它不起作用 - 通过这个灵魂

检查猫鼬文档后,它似乎是正确的,但它不起作用。

我的旅游架构:

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
});

我的reviewSchema:**我在巡演中使用了review schema,并且用户填充了巡演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 内是否存在填充未针对正确字段的选项?

标签: javascriptnode.jsmongoose

解决方案


您需要一个选项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 });

虽然我猜这不是绝对必要的。


推荐阅读