繁体   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