#node.js #mongodb #mongoose
Вопрос:
Я работаю над сайтом с каталогом магазинов, где пользователи могут оставлять комментарии и оценивать эти магазины.
Мой код до сих пор:
Схемы:
const journalSchema = new mongoose.Schema({
title: String,
category: String,
subcategory: String,
review: [{type: mongoose.Schema.Types.ObjectId, ref: 'Review'}],
link: String,
description: String,
});
const userSchema = new mongoose.Schema ({
username: String,
nickname: String,
password: String,
journal: [{type: mongoose.Schema.Types.ObjectId, ref: 'Journal'}]
});
const reviewSchema = new mongoose.Schema({
author: {type: mongoose.Schema.Types.String, ref: 'User'},
content: String,
date: Date,
rating: Number
});
const Journal = mongoose.model("Journal", journalSchema);
const User = mongoose.model("User", userSchema);
const Review = mongoose.model("Review", reviewSchema);
Получить маршрут для отдельной страницы магазина:
app.get("/journals/:journalId", function(req, res){
const requestedJournalId = req.params.journalId;
Journal.findOne({_id: requestedJournalId}, function(err, foundJournal){
Review.aggregate([
{$match: {_id: {$in: foundJournal.review}}},
{$group: {_id: foundJournal.review, average: {$avg: "$rating"}}}
], function(err, result){
if(err){
console.log(err);
}
else{
result.forEach(function(review){
Review.find({_id: review._id}, function(err, reviews){
res.render("stats", {
_id: foundJournal._id,
title: foundJournal.title,
subcategory: foundJournal.subcategory,
link: foundJournal.link,
description: foundJournal.description,
reviews: reviews,
avg: review.average
});
})
})
}
});
})
});
Почтовый маршрут:
app.post("/stats/review", function(req, res){
if(req.isAuthenticated()){
const userId = req.user.id;
const userReview = req.body.journalReview;
const userRating = req.body.reviewRating;
const journalId = req.body.journalId;
User.findById(userId, function(err, foundUser){
if(err){
console.log(err);
}
else{
const review = new Review();
review.author = foundUser.nickname;
review.content = userReview;
review.rating = userRating;
review.save()
.then((result) =>{
Journal.findOneAndUpdate(
{_id: journalId},
{$push: {
review: review
}},
{useFindAndModify: false},
function(err, success){
if(err){
console.log(err);
}
else{
res.redirect("back");
}
}
);
})
.catch((error) =>{
console.log(error);
})
}
});
}
else{
res.redirect("/login");
}
});
В настоящее время код работает и делает то, что я хочу, чтобы он делал. Любой вошедший в систему пользователь может оставить комментарий и рейтинг для любого магазина. Но меня беспокоит, как улучшить существующий код, я уверен, что есть лучшие способы достичь того же результата с более чистым и эффективным кодом. Я новичок в мангусте и совсем недавно узнал о методе агрегирования. Заранее спасибо
Ответ №1:
Вы можете использовать ES6 для лучшего форматирования кода. вот ссылка, по которой вы можете перейти:https://www.w3schools.com/js/js_es6.asp
Я отформатировал маршрут для вашего понимания:
app.get("/journals/:id", async (req, res) => {
const journal = await Journal.findOne(req.params.id);
if (!journal) {
res.status(404).sent({ error: "journal not found" });
}
try {
const reviews = await Review.aggregate([
{ $match: { _id: { $in: journal.review } } },
{
$group: {
_id: journal.review,
average: { $avg: "$rating" },
},
},
]);
reviews.forEach((review) => {
const reviews = await Review.find({ _id: review._id });
res.render("stats", {
...journal,
reviews,
avg: review.average,
});
});
} catch (error) {
console.log(error);
res.status(400).send(error);
}
});
- вы можете использовать
mongoose-autopopulate
пакет для автоматического заполнения вашего документа. https://www.npmjs.com/package/mongoose-autopopulate - избегайте использования вложенных запросов к базе данных.
- попробуйте реализовать
async await
для лучшей читабельности.