簡體   English   中英

mongodb / mongoose聚合結合了兩個表/集合

[英]mongodb/mongoose aggregation that combine two table/collection

我在節點js中使用mLab來存儲數據庫和貓鼬,我正在使用swagger這應該不會造成任何問題。 我有以下架構。 當用戶請求時,如果查詢中(review = true),我需要返回電影並一起查看。 一部電影可能有多個評論。 首先,我必須在數據庫中查找所有電影。 當我找到電影時,我必須仔細閱讀每個電影,在另一個數據庫中查找任何評論,然后以某種方式將它們附加在電影中。 我需要將所有電影放回一個包中,因為它將用於getAll功能。 不管我做什么,只返回沒有評論的電影。

 var mongoose = require('mongoose'); var reviewSchema = new mongoose.Schema({ movie: {type: String, required: true}, reviewer: {type: String, required: true}, rating: {type: Number, required:true, min: 1, max: 5}, text: {type: String, required: true}, }) var movieSchema = new mongoose.Schema({ Title: {type: String, required: true, unique: true}, YearReleased: {type: Number, required: true}, Actors: [{ Name: {type: String, required: true} }] }) 

 function getAll(req,res,next){ db.Movies.find({},function(err,movies){ if(err) throw {err:err}; if(req.swagger.params.review.value === false) res.send({Movielist: movie}); else { movies.forEach(function(movie, index){ db.Reviews.find({movie:movies[index].Title}, function (err, review) { if(err) throw {err:err} movies[index].Review = review // I am trying to populate each movie with reviews }); }); res.send({Movielist: movies}); } }); } 

在收到數據庫評論結果之前調用res.send:

        movies.forEach(function(movie, index){
            // this call is asynchronous, res.send will run before the callback
            db.Reviews.find({movie:movies[index].Title}, function (err, review) {
                if(err) throw {err:err}
                movies[index].Review = review    // I am trying to populate each movie with reviews
            });
        });
        res.send({Movielist: movies});

您可以使用Promise等待結果。 我將以async / await為例。 也可以使用不帶異步/等待的promise。

async function getAll(req,res,next) {
  try {
    let movies = await getMovies();
    res.send(movies);
  } catch (err) {
    console.log(err.stack);
  }
}

async function getMovies () {
  return new Promise(function (resolve, reject) {
    db.Movies.find({},function(err,movies){
      if(err) reject(err);
      if(req.swagger.params.review.value === false)
          resolve({Movielist: movie});
      else {
        movies.forEach(function(movie, index){
          let review = await getReviews();
          movies[index].Review = review
        });
        resolve({Movielist: movies});
      }
    });
  });
}

async function getReviews (movie, index) {
  return new Promise(function (resolve, reject) {
    db.Reviews.find({movie:movies[index].Title}, function (err, review) {
        if(err) reject({err:err});
        resolve(review);
    });
  });
}

由於我尚未測試,因此可能需要進行一些調整。 我希望它能給出解決此問題的總體思路。

如果沒有異步/等待,則可以調用promises並運行“ .then”以處理結果。 如果您沒有使用諾言,那么一些Google搜索應該可以幫助您了解.then的工作方式。

首先,謝謝@curtwphillips,但我發現這樣做的捷徑。 但是,要使此工作正常進行,電影和評論必須與不同收藏集放在同一數據庫中。 如果您使用其他數據庫,則無法使用

 function getAll(req,res,next) { if (req.query.review === 'true') { db.Movies.aggregate([ { $lookup: { from: "reviews", localField: "Title", foreignField: "movie", as: "review" } } ], function (err, result) { if (err) throw {err: err}; else { res.send({Movielist: result}); } }); } else { db.Movies.find({}, function (err, movies) { if (err) throw {err: err}; res.send({Movielist: movies}) }) } } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM