-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreviewModel.js
executable file
·103 lines (92 loc) · 2.19 KB
/
reviewModel.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// review / rating / createdAt / ref to tour / ref to user
const mongoose = require('mongoose');
const Tour = require('./tourModel');
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 belong to a tour.']
},
user: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: [true, 'Review must belong to a user']
}
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true }
}
);
reviewSchema.index({ tour: 1, user: 1 }, { unique: true });
reviewSchema.pre(/^find/, function(next) {
// this.populate({
// path: 'tour',
// select: 'name'
// }).populate({
// path: 'user',
// select: 'name photo'
// });
this.populate({
path: 'user',
select: 'name photo'
});
next();
});
reviewSchema.statics.calcAverageRatings = async function(tourId) {
const stats = await this.aggregate([
{
$match: { tour: tourId }
},
{
$group: {
_id: '$tour',
nRating: { $sum: 1 },
avgRating: { $avg: '$rating' }
}
}
]);
// console.log(stats);
if (stats.length > 0) {
await Tour.findByIdAndUpdate(tourId, {
ratingsQuantity: stats[0].nRating,
ratingsAverage: stats[0].avgRating
});
} else {
await Tour.findByIdAndUpdate(tourId, {
ratingsQuantity: 0,
ratingsAverage: 4.5
});
}
};
reviewSchema.post('save', function() {
// this points to current review
this.constructor.calcAverageRatings(this.tour);
});
// findByIdAndUpdate
// findByIdAndDelete
reviewSchema.pre(/^findOneAnd/, async function(next) {
this.r = await this.findOne();
// console.log(this.r);
next();
});
reviewSchema.post(/^findOneAnd/, async function() {
// await this.findOne(); does NOT work here, query has already executed
await this.r.constructor.calcAverageRatings(this.r.tour);
});
const Review = mongoose.model('Review', reviewSchema);
module.exports = Review;