Раздел комментариев с мангустом и node.js

#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 для лучшей читабельности.