虚拟人口猫鼬

时间:2020-09-23 15:50:59

标签: javascript node.js mongoose

我尝试在创建的两个模型之间使用虚拟填充: 在这种情况下,将获得所有具有游览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内,是否存在填充对象未定位到正确字段的选项?

2 个答案:

答案 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将虚拟填充到巡回赛中