2012-04-03 62 views
2

我将如何创建一个查询来获得当前球员的排名和周围球员的排名。举例来说,如果我有一个排行榜的收集与名字,并指出孟戈与周围球员排名排行榜

{name: 'John', pts: 123} 

如果约翰在第23位,我会想显示在第22和第24位的用户的名称为好。

我可以查询点数大于123的排行榜物品的数量来得到约翰的排名,但是我怎样才能有效地获得排名在当前玩家之上和之下的玩家?我可以根据索引位置单独获取项目吗?

我想我可以做2个查询,率先拿到号码的用户,然后跳过限制查询的排名位置,但似乎效率低下,似乎没有一个高效使用索引

db.leaderboards.find({pts:{$gt:123}}).count(); 
-> 23 

db.leaderboards.find().skip(21).limit(3) 

最后一个查询似乎使用其索引扫描了24条记录,有没有一种方法可以合理地做到这一点与范围查询或更有效的?如果用户排名很低,比如第50,000个,我可以看到这成为一个问题。

回答

2

你需要做三个查询:

var john = db.players.findOne({name: 'John'}) 
var next_player = db.players.find(
    {_id: {$ne: john._id}, pts: {$gte: john.pts}}).sort({pts:1,name:1}).limit(-1)[0] 
var previous_player = db.players.find(
    {_id: {$ne: john._id}, pts: {$lte: john.pts}}).sort({pts:-1,name:-1}).limit(-1)[0] 

创建的名称和分指标。

+0

谢谢,你如何确保它是相邻的记录,而不是任何大于或小于的记录..因为我没有看到它。另外,我试着用explain()来查看执行的查询,并且它似乎没有与findOne一起工作。我如何看待它使用的索引。 – MonkeyBonkey 2012-04-03 16:39:48

+0

colleciton.find({... query ...})。limit(-1).explain()等同于解释findOne()。 – 2012-04-03 16:42:37

+0

所以在next_player查询中,我如何确保它是下一个相邻的排名,而不仅仅是比当前玩家更高的排名? – MonkeyBonkey 2012-04-04 23:59:42