简体   繁体   中英

How can i access field from another model in mongoose model

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM