아래에서 사용할 Tour 스키마 예시
const tourSchema = new mongoose.Schema(
{
name: {
type: String,
required: [true, 'A tour must have a name'],
unique: true,
trim: true,
maxlength: [40, 'A tour name must have less or equal then 40 characters'],
minlength: [10, 'A tour name must have more or equal then 10 characters'],
},
slug: String,
duration: {
type: Number,
required: [true, 'A tour must have a duration'],
},
maxGroupSize: {
type: Number,
required: [true, 'A tour must have a group size'],
},
difficulty: {
type: String,
required: [true, 'A tour must have a difficulty'],
enum: {
values: ['easy', 'medium', 'difficult'],
message: 'Difficulty is either: easy, medium, difficult',
},
},
ratingsAverage: {
type: Number,
default: 4.5,
min: [1, 'Rating must be above 1.0'],
max: [5, 'Rating must be below 5.0'],
},
ratingsQuantity: {
type: Number,
default: 0,
},
price: {
type: Number,
required: [true, 'A tour must have a price'],
},
priceDiscount: {
type: Number,
validate: {
validator: function (val) {
// this only points to current doc on NEW document creation
return val < this.price;
},
message: 'Discount price ({VALUE}) should be below regular price',
},
},
summary: {
type: String,
trim: true,
required: [true, 'A tour must have a description'],
},
description: {
type: String,
trim: true,
},
imageCover: {
type: String,
required: [true, 'A tour must have a cover image'],
},
images: [String],
createdAt: {
type: Date,
default: Date.now(),
select: false,
},
startDates: [Date],
secretTour: {
type: Boolean,
default: false,
},
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true },
}
);
1. virtual
스키마를 선언 할 때 타입을 고정으로 할 수 도 있지만, virtual을 이용하면 스키마에 선언되어 있지 않은 가상 필드를 만들어 준다.
tourSchema.virtual('durationWeek').get(function() { return this.duration / 7 })
여기에서 화살표 함수를 사용하지 않고, function 키워드를 사용한 이유는
this
를 접근하기 위함이다.this
를 통해 tour 모델 인스턴스에 접근 할 수 있다.{ ... durationWeek: 1 }
2. methos
인스턴스에서 접근할 수 있는 메소드를 선언 할 수 있다.
코드 재활용면에서 굉장히 효과적이다.
가격이 N원 이상인 여행일 경우 예외처리를 한다면...
tourSchema.methods.checkPrice = function(price, cb) { if (this.price > price) { return cb('요청한 가격보다 높게 책정되어 있습니다.') } cb(null, true) }
tour.checkPrice(30000, function(err, result) { if (err) { throw err } // ...do something with result })
3. pre / post
특정 동작 이전, 이후에 어떤 행동을 취할 지 정의 할 수 있습니다.
pre는 미들웨어 같은 느낌으로 생각하면 됩니다.
tourSchema.pre('save', function(next) { // 가격이 30000원이 넘으면 저장하지 않기 if (this.price > 30000) { throw '30000원이 넘습니다.' } next() }) tourSchema.post('save', function(doc, next) { console.log('저장 완료') next() })