def zrangebyscore(self, key, min_score, max_score, withscores=False, offset=0, count=float('+inf')): result = [] num_elems_read = 0 if withscores: num_elems_per_entry = 2 else: num_elems_per_entry = 1 score_range = ScoreRange(min_score, max_score) for db_key in self._db.iterator( prefix=KEY_CODEC.get_min_zset_score(key), include_value=False): if len(result) / num_elems_per_entry >= count: return result db_score = KEY_CODEC.decode_zset_score(db_key) if score_range.above_max(db_score): break if score_range.check(db_score): num_elems_read += 1 if len(result) / num_elems_per_entry >= count: return result if num_elems_read > offset: db_value = KEY_CODEC.decode_zset_value(db_key) result.append(db_value) if withscores: result.append(db_score) return result
def zrange(self, key, start, stop, with_scores): result = [] zset_length = int(self._db.get(KEY_CODEC.encode_zset(key), '0')) if stop < 0: end = zset_length + stop else: end = stop if start < 0: begin = max(0, zset_length + start) else: begin = start for i, (db_key, _) in enumerate( self._get_db_iterator(KEY_CODEC.get_min_zset_score(key))): if i < begin: continue if i > end: break db_score = KEY_CODEC.decode_zset_score(db_key) db_value = KEY_CODEC.decode_zset_value(db_key) result.append(db_value) if with_scores: result.append(db_score) return result
def zrank(self, key, member): score = self._db.get(KEY_CODEC.encode_zset_value(key, member)) if score is None: return None rank = 0 for db_key, _ in self._get_db_iterator( KEY_CODEC.get_min_zset_score(key)): db_score = KEY_CODEC.decode_zset_score(db_key) db_value = KEY_CODEC.decode_zset_value(db_key) if db_score < float(score): rank += 1 elif db_score == float(score) and db_value < member: rank += 1 else: break return rank
def zcount(self, key, min_score, max_score): # TODO: optimize for performance. it's probably possible to create a new entry only for scores # like: # <prefix>myzset<score> = number of elements with that score # # ZADD myzset 10 a # <prefix>_myzset_10 = 1 ; one element with score 10 # # ZADD myzset 10 b # <prefix>_myzset_10 = 2 ; two elements with score 10 score_range = ScoreRange(min_score, max_score) count = 0 for db_key, _ in self._get_db_iterator( KEY_CODEC.get_min_zset_score(key)): db_score = KEY_CODEC.decode_zset_score(db_key) if score_range.check(db_score): count += 1 if score_range.above_max(db_score): break return count
def get_key_value_pair(db_key, db_value): field = KEY_CODEC.decode_zset_value(db_key) value = KEY_CODEC.decode_zset_score(db_key) return field, value