Here is something to get you started in Python:
from operator import itemgetter
import fdb
from fdb.tuple import pack
from fdb.tuple import unpack
fdb.api_version(510)
@fdb.transactional
def get_score(tr, user):
"""Return the score of the user.
Add the user to the leaderboard if they are not already there
"""
user_key = pack(('scores', user))
score = tr.get(user_key)
if score == None:
# init the score at zero
score = 0
tr.set(user_key, pack((score,)))
# Also store the user in the leaderboard.
# Here the value is empty and the full data is encoded
# in the key in order to make each key unique and keep
# the leaderboard sorted.
tr.set(pack(('leaderboard', score, user)), b'')
else:
score = unpack(score)[0]
return score
@fdb.transactional
def add(tr, user, increment=1):
"""Add INCREMENT to USER score.
Return the new score of the user"""
score = get_score(tr, user)
total = score + increment
# update the user's score...
user_key = pack(('scores', user))
tr.set(user_key, pack((total,)))
# ...and the leaderboard
tr.clear(pack(('leaderboard', score, user)))
tr.set(pack(('leaderboard', total, user)), b'')
return total
@fdb.transactional
def top(tr, count=3):
out = dict()
# iterate over the whole 'leaderboard' namespace in reverse order
iterator = tr.get_range_startswith(pack(('leaderboard',)), reverse=True)
for key, _ in iterator:
_, score, user = unpack(key)
if score in out.keys():
out[score].append(user)
elif len(out.keys()) == count:
break
else:
out[score] = [user]
# output a sorted dict (python >= 3.6)
return dict(sorted(out.items(), key=itemgetter(0), reverse=True))
Here is an example REPL run:
In [1]: import fdb
In [2]: import leaderboard
In [3]: db = fdb.open()
In [4]:
In [4]: leaderboard.add(db, 'amirouche', 42)
Out[4]: 42
In [5]: leaderboard.top(db)
Out[5]: {0: ['nitu'], 42: ['amirouche']}
In [6]: leaderboard.add(db, 'nitu', 42)
Out[6]: 42
In [7]: leaderboard.top(db)
Out[7]: {42: ['nitu', 'amirouche']}
In [8]: leaderboard.add(db, 'amirouche', 42)
Out[8]: 84
In [9]: leaderboard.top(db)
Out[9]: {42: ['nitu'], 84: ['amirouche']}
Feel free to ask question, there is no stupid question, especially at this point.
Also, I’ve been answering question about how to create applications ontop key-value stores on stackoverflow, see “Find by value on leveldb” and “Key Value Store in NoSQL Database Systems”.
BTW, before some ask the question, I don’t think it’s worth learning wiredtiger or leveldb or lmdb at this point (except maybe if you plan to do event sourcing like SkuVault).
edit: copy/paste failure