В моих NodeJS API и MongoDB я добавил 2 метода для обновления и удаления отзыва. Обзор содержит средние значения показателей для 4 категорий на данный момент. Когда я обновляю, AVG также обновляется до нового расчета, а также, когда я удаляю, AVG обновляется. Эти 2 метода являются общими для расчета AVG, и мне нужно будет создать модуль, который содержит вычисления AVG и будет использоваться внутри 2 методов или там, где это потребуется.
Тело обзора при обновлении:
{
"Rating": 3,
"GoodService": 4,
"WifiRate": 4,
"QuitePlace": 4,
"Text": "Am I updating in the right way"
}
Эти цифры от 1 до 5, поэтому пользователь может голосовать в этом диапазоне, а AVG рассчитываются и добавляются в документ мест следующим образом:
{
"RateAVG": 4.5
"GoodService": 2.5,
"QuitePlace": 2.5,
"WifiRate": 2.5,
}
Методы обновления и удалите, как следует, и вы заметите, что в 2 методах вычисление AVG включено в метод синглов, и вот решение, которое я ищу, состоит в том, чтобы сделать этот код более эффективным и элегантным для совместного использования в модуле для вычисления AVG, а не так, как сейчас
async updateReview(req, res, next) {
try {
// eslint-disable-next-line no-underscore-dangle
const { placeId, reviewId } = req.params;
const userId = req.user._id.toString();
const reviewData = await DB.Review.findById(reviewId);
const incomingData = req.body;
const updateRating = {};
if (reviewData.UserId.equals(userId)) {
const update = await DB.Review.findByIdAndUpdate(
reviewId,
incomingData,
{ new: true },
);
// update place's Review[] first
const updatePlaceRating = await DB.Place.updateOne(
{
Reviews: {
$elemMatch: {
_id: reviewId,
},
},
},
{
$set: {
'Reviews.$.Rating': incomingData.Rating,
'Reviews.$.GoodService': incomingData.GoodService,
'Reviews.$.QuitePlace': incomingData.QuitePlace,
'Reviews.$.WifiRate': incomingData.WifiRate,
'Reviews.$.Text': incomingData.Text,
},
},
);
const updatedPlaceData = await DB.Place.findById(placeId);
const updatedReviewData = updatedPlaceData.Reviews;
let rateAverage = 0;
let goodService = 0;
let quitePlace = 0;
let wifiRate = 0;
for (let i = 0; i < updatedReviewData.length; i += 1) {
rateAverage += updatedReviewData[i].Rating;
goodService += updatedReviewData[i].GoodService;
quitePlace += updatedReviewData[i].QuitePlace;
wifiRate += updatedReviewData[i].WifiRate;
}
// calculate now place params
updateRating.RateAverage =
updatedReviewData.length > 0
? Math.floor((rateAverage / updatedReviewData.length) * 100) / 100
: 0;
updateRating.GoodService =
updatedReviewData.length > 0
? Math.floor((goodService / updatedReviewData.length) * 100) / 100
: 0;
updateRating.QuitePlace =
updatedReviewData.length > 0
? Math.floor((quitePlace / updatedReviewData.length) * 100) / 100
: 0;
updateRating.WifiRate =
updatedReviewData.length > 0
? Math.floor((wifiRate / updatedReviewData.length) * 100) / 100
: 0;
updateRating.Text = incomingData.Text;
// Now update place params for rating
const updatePlace = await DB.Place.findByIdAndUpdate(
placeId,
updateRating,
{ new: true },
);
if (!updatePlaceRating || !updatePlace || !update) {
Logger.error('Update error');
return res.status(500).json('Update error');
}
Logger.info('Update success');
return res.status(200).json(update);
}
Logger.error('Not authorized');
return res.status(404).json('Not authorized');
} catch (err) {
Logger.error(err);
return next(err);
}
},
async deleteReview(req, res, next) {
try {
// eslint-disable-next-line no-underscore-dangle
const userId = req.user._id.toString();
const review = await DB.Review.findById(req.params.reviewId);
if (review.UserId.equals(userId)) {
const removed = await DB.Review.findByIdAndRemove(req.params.reviewId);
// update place's Review[] first
const removePlaceRating = await DB.Place.updateOne(
{
Reviews: {
$elemMatch: {
_id: req.params.reviewId,
},
},
},
{
$pull: { Reviews: { _id: req.params.reviewId } },
},
);
const updatedPlaceData = await DB.Place.findById(req.params.placeId);
const updatedReviewData = updatedPlaceData.Reviews;
let rateAverage = 0;
let goodService = 0;
let quitePlace = 0;
let wifiRate = 0;
for (let i = 0; i < updatedReviewData.length; i += 1) {
rateAverage += updatedReviewData[i].Rating;
goodService += updatedReviewData[i].GoodService;
quitePlace += updatedReviewData[i].QuitePlace;
wifiRate += updatedReviewData[i].WifiRate;
}
const updateRating = {};
// calculate now place params
updateRating.RateAverage =
updatedReviewData.length > 0
? rateAverage / updatedReviewData.length
: 0;
updateRating.GoodService =
updatedReviewData.length > 0
? goodService / updatedReviewData.length
: 0;
updateRating.QuitePlace =
updatedReviewData.length > 0
? quitePlace / updatedReviewData.length
: 0;
updateRating.WifiRate =
updatedReviewData.length > 0
? wifiRate / updatedReviewData.length
: 0;
// Now update place params for rating
const updatePlace = await DB.Place.findByIdAndUpdate(
req.params.placeId,
updateRating,
{ new: true },
);
if (removed && removePlaceRating && updatePlace) {
return res.status(200).json('Removed');
}
return res.status(404).json('Review not found');
}
return res.status(401).json('not authorised');
} catch (err) {
Logger.error(err);
return next(err);
}
},