将两个查询结果传递到响应中

Posted

技术标签:

【中文标题】将两个查询结果传递到响应中【英文标题】:Passing two query results into a response 【发布时间】:2015-11-19 21:28:06 【问题描述】:

我有一个查询可以获取排行榜的前 5 名。在 robomongo 中,此查询工作正常。

当我做类似的事情时

var leaderboard = User.find(points: $exists: true, 
    "firstname": 1,
    "lastname": 1,
    "points": 1
).sort(points : -1).limit(5)
 console.log('leaderboard');

我得到了很多毫无意义的 json 和 [object] 几乎无处不在。

我将如何执行此查询以与 mongoose + express 一起使用,以便我可以将视图作为数组传递给

firstname, lastname, points 

所以我可以在视图中循环它?

我的完整代码是

app.get('/dashboard', function(req, res)

  if (req.user) 
    // logged in

   User.find(, function(err, docs) 
      // console.log(docs);
  );

    // Get total points after submit
  var leaderboard = User.find(points: $exists: true, 
      "firstname": 1,
      "lastname": 1,
      "points": 1
  ).sort(points : -1).limit(5).toArray();
  console.log(leaderboard);

  User.find(
      points: 
          $exists: true
      
  , function(err, docs) 
      if(err)
          console.log(err);
          //do error handling
      
      //if no error, get the count and render it
      var count = 0;
      for (var i = 0; i < docs.length; i++) 
          count += docs[i].points;
      
      var totalpoints = count;

      res.render('dashboard', 
      title: 'Dashboard',
      user: req.user,
      totalpoints: totalpoints
      );
  );

   else 
    // not logged in
    return res.redirect('/login');
    

);

【问题讨论】:

就像您稍后在代码中所做的那样,您只能通过回调获得结果。 “无意义的[对象]”实际上是“光标”的定义,因为查询没有执行。 是否可以让它在同一个回调中查询? 【参考方案1】:

所以你实际上只是在这里返回一个游标而不执行查询。您当然可以始终嵌套查询,但您可以更好地使用async.waterfall 来避免缩进混乱。

另外我会使用.aggregate(),而不是循环所有文档来获取总数。并且 mongoose 会自动将结果转换为数组,因此这里不需要 .toArray()

app.get('/dashboard', function(req, res)

  if (req.user) 
    // logged in

    async.waterfall(
      [
        function(callback) 
          User.find(
             "points":  "$exists": true  ,
            
              "firstname": 1,
              "lastname": 1,
              "points": 1
            
          ).sort(points : -1).limit(5).exec(callback);
        ,
        function(leaderboard,callback) 
          User.aggregate(
            [
               "$match":  "points":  "$exists": true  ,
               "$group": 
                "_id": null,
                "totalpoints":  "$sum": "$points" 
              
            ],
            function(err,result) 
              callback(err,result,leaderboard)
            
          );
        
      ],
      function(err,result,leaderboard) 
        if (err) 
            console.log(err);
            //do error handling
         else 
          res.render('dashboard', 
            title: 'Dashboard',
            user: req.user,
            totalpoints: result[0].totalpoints,
            leaderboard: leaderboard
          );
        
      
    );
   else 
    // not logged in
    return res.redirect('/login');
  

);

所以你得到你的leaderboard 结果并将其放入响应中,就像在此处的示例中所做的那样。

另一种方法是使用async.parallel,因为您不需要在第二个查询中输出第一个查询。在这种情况下,两个查询的结果都会在最后发送到回调,就像上面一样。同样,您只需在最终回复中使用结果。

app.get('/dashboard', function(req, res)

  if (req.user) 
    // logged in

    async.parallel(
      
        "leaderboard": function(callback) 
          User.find(
             "points":  "$exists": true  ,
            
              "firstname": 1,
              "lastname": 1,
              "points": 1
            
          ).sort(points : -1).limit(5).exec(callback);
        ,
        "totalpoints":function(callback) 
          User.aggregate(
            [
               "$match":  "points":  "$exists": true  ,
               "$group": 
                "_id": null,
                "totalpoints":  "$sum": "$points" 
              
            ],
            function(err,result) 
              callback(err,result[0].totalpoints)
            
          );
        
      ,
      function(err,results) 
        if (err) 
            console.log(err);
            //do error handling
         else 
          res.render('dashboard', 
            title: 'Dashboard',
            user: req.user,
            totalpoints: results.totalpoints,
            leaderboard: results.leaderboard
          );
        
      
    );
   else 
    // not logged in
    return res.redirect('/login');
  

);

【讨论】:

似乎我有很多关于 mongodb 实践的内容要阅读。感谢您提供如此详细的解释,我是 mongo 的新手,这对我有很大帮助! @ServerSideSkittles 您肯定想阅读aggregation framework,因为这是一个数据库,您通常不希望在代码中迭代文档。还添加了一个使用async.parallel 的列表,它确实应该更适合这个目的。

以上是关于将两个查询结果传递到响应中的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Node.js 的一个 json 中附加两个查询结果

访问:从表单传递参数到查询

使用 PostgreSQL 将两个选择查询的结果添加到一个表行中

我如何将两个数据框列值作为键传递给2键到一个值字典,然后将结果传递到另一列?

如何将两个查询的结果合并到一个数据集中

axios 调用从第一个 api 获取响应并传递到第二个 api