将两个查询结果传递到响应中
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 将两个选择查询的结果添加到一个表行中