I'm new to MongoDB (+Mongoose). I have a collection of highscores with documents that looks like this:
{id: 123, user: 'User14', score: 101}
{id: 231, user: 'User10', score: 400}
{id: 412, user: 'User90', score: 244}
{id: 111, user: 'User12', score: 310}
{id: 221, user: 'User88', score: 900}
{id: 521, user: 'User13', score: 103}
+ thousands more...
now I'm getting the top 5 players like so:
highscores
.find()
.sort({'score': -1})
.limit(5)
.exec(function(err, users) { ...code... });
which is great, but I would also like to make a query like "What placement does user12
have on the highscore list?"
Is that possible to achieve with a query somehow?
If you don't have to get the placement in real time, Neil Lunn's answer is perfect. But if your app has always data to insert in this collection, for the new data, you can't get the placement for it.
Here is another solution:
Firstly, you add index on the field score in this collection. Then use query
db.highscores.count({score:{$gt: user's score})
. It will count the documents whose score it greater than the target. This number is the placement.It is possible to do this with mapReduce, but it does require that you have an index on the sorted field, so first, if you already have not done:
Then you can do this:
Or vary that to the information you need to return other than simply the "ranking" position. But since that is basically putting everything into a large array that has already been sorted by score then it probably will not be the best performance for any reasonable size of data.
A better solution would be to maintain a separate "rankings" collection, which you can again update periodically with mapReduce, even though it does not do any reducing:
Then you can query this collection in order to get your results:
So that would contain the ranking as "emitted" in the
_id
field of the "rankings" collection.