Reputation: 39
I made have here two MongoDB Models
Movie Model
import mongoose from 'mongoose';
const movieSchema = new mongoose.Schema({
title: {
type: String,
required: [true, 'Please Enter the Movie Title'],
trim: true,
minlength: 5,
maxlength: 255
},
genre: {
type: mongoose.Schema.ObjectId,
ref: 'Genre',
required: true
},
year: {
type: Number,
min: 1800,
max: 3000,
required: [true, 'Please enter the year of the movie.']
},
directors: [
{
type: String,
minlength: 5,
maxlength: 100
}
],
writers: [
{
type: String,
minlength: 5,
maxlength: 100
}
],
cast: [
{
type: String,
minlength: 5,
maxlength: 100
}
],
numberInStock: {
type: Number,
required: true,
min: 0,
max: 255
},
dailyRentalRate: {
type: Number,
required: true,
min: 0,
max: 255
}
});
export default mongoose.model('Movie', movieSchema);
Rental Model
import mongoose from 'mongoose';
import moment from 'moment';
const rentalSchema = new mongoose.Schema({
customer: {
type: mongoose.Schema.ObjectId,
ref: 'Customer',
required: true
},
movie: {
type: mongoose.Schema.ObjectId,
ref: 'Movie',
required: true
},
dateOut: {
type: Date,
required: true,
default: Date.now
},
dateReturned: {
type: Date
},
rentalFee: {
type: Number,
min: 0
}
});
rentalSchema.methods.return = function () {
this.dateReturned = new Date();
this.rentalFee =
moment().diff(this.dateOut, 'days') * this.movie.dailyRentalRate;
};
export default mongoose.model('Rental', rentalSchema);
Return Controller
import catchAsync from '../utils/catchAsync.js';
import AppError from '../utils/appError.js';
import Rental from '../models/rentalModel.js';
import Movie from '../models/movieModel.js';
const returns = catchAsync(async (req, res, next) => {
const rental = await Rental.findOne({
customer: req.body.customerID,
movie: req.body.movieID
});
// console.log(rental);
if (!rental) {
return next(new AppError('Not Found', 400));
}
if (rental.dateReturned) {
return next(new AppError('Already Returned', 400));
}
rental.return();
await rental.save();
// add movie back into stock
await Movie.updateOne(
{ _id: rental.movie._id },
{
$inc: { numberInStock: 1 }
}
);
res.status(400).json({
status: 'success',
rental
});
});
export default returns;
Return Route
import { Router } from 'express';
import { protect } from '../controllers/authController.js';
import returns from '../controllers/returnController.js';
const router = Router();
router.post('/', protect, returns);
export default router;
The problem is that when i want to access the movie field in Rental Model it will return the movie ID but i want it to return object contains the movie data (something like populate but inside the Model Logic) so if i tried to access this.movie.dailyRentalRate it returns value not undefined
Upvotes: 0
Views: 2152
Reputation: 5051
MongoDB has the $lookup
aggregation
operator. Mongoose has alternative called populate()
, which lets you ref documents in other collections.Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s) so you can use populate for your problem like this:
const rental = await Rental.findOne({
customer: req.body.customerID,
movie: req.body.movieID
}).populate("movie")
it's worked to me, and in the methods.return
you access to the this.movie.dailyRentalRate
Upvotes: 1