I want to implement internet high scores for my game. And give feedback to players which place they have (not only top100 or something like that). In normal SQL it would look like that:
SELECT COUNT(*) FROM Scores WHERE points > :newUsersPoints
and GQL have something similar
db.GqlQuery("SELECT * FROM Score WHERE points > :1", newUsersPoints).count()
but since count() is limited only to 1000 it won't be very useful in my case. Do you have any ideas on how to implement this?
I have two
First:
Use sharding counters idea (http://code.google.com/intl/pl/appengine/articles/sharding_counters.html) Create new "table" that stores how many scores are in some range(from_points, to_points)
Sum up all counters from above table where range.to_points < newUsersPoints
Find how many scores are bigger than scores in range where the new score is db.GqlQuery("SELECT * FROM Score WHERE points > :1 AND points >= :2 AND points < :3", newUsersPoints, range.from_points, range.to_points).count() + sumfrom2
Find range in which new score is in and increment its counter
Split ranges which counter is bigger than 1000 (or 999) so that 3. wouldn't reach the limit
Add new score to scores table
Which is quite complicated and error prone. We might increment some range and Timeout before adding the score. (not transactional)
Second idea:
From time to time (once every day?) sort all scores by points and give them new positions (script might Timeout so we have to do it in chunks)
To find out at which place new score is we just do
db.GqlQuery("SELECT * FROM Score WHERE points > :1 LIMIT 1", newUsersPoints).get().precalculated_position + 1
Any other ideas?