Skip to content

Commit

Permalink
Feat: add withscore option for EXZRANK and EXZREVRANK. (#18)
Browse files Browse the repository at this point in the history
Add withscore option for EXZRANK and EXZREVRANK
  • Loading branch information
RinChanNOWWW authored Dec 2, 2022
1 parent 9927838 commit 2a7d863
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 29 deletions.
8 changes: 6 additions & 2 deletions CMDDOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,22 +205,26 @@ Returns the tairzset cardinality (number of elements) of the tairzset stored at
#### Return value
Integer reply: the cardinality (number of elements) of the tairzset, or 0 if key does not exist.
### EXZRANK
> EXZRANK key member
> EXZRANK key member [WITHSCORE]
> time complexity:O(log(N))
#### Command Description:
Returns the rank of member in the tairzset stored at key, with the scores ordered from low to high. The rank (or index) is 0-based, which means that the member with the lowest score has rank 0.

The optional WITHSCORES argument makes the command return both the ranke and the score, instead of the rank alone.

Use EXZREVRANK to get the rank of an element with the scores ordered from high to low.
#### Return value
If member exists in the tairzset, Integer reply: the rank of member.
If member does not exist in the tairzset or key does not exist, Bulk string reply: nil.
### EXZREVRANK
> EXZREVRANK key member
> EXZREVRANK key member [WITHSCORE]
> time complexity:O(log(N))
#### Command Description:
Returns the rank of member in the tairzset stored at key, with the scores ordered from high to low. The rank (or index) is 0-based, which means that the member with the highest score has rank 0.

The optional WITHSCORES argument makes the command return both the ranke and the score, instead of the rank alone.

Use EXZRANK to get the rank of an element with the scores ordered from low to high.

#### Return value
Expand Down
39 changes: 33 additions & 6 deletions src/tairzset.c
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ static void exZaddGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv,
RedisModule_Free(scores);
}

long exZsetRank(TairZsetObj *zobj, RedisModuleString *ele, int reverse, int byscore) {
long exZsetRank(TairZsetObj *zobj, RedisModuleString *ele, int reverse, int byscore, scoretype **return_score) {
unsigned long llen;
unsigned long rank;

Expand All @@ -767,6 +767,9 @@ long exZsetRank(TairZsetObj *zobj, RedisModuleString *ele, int reverse, int bysc
if (de != NULL) {
scoretype *score = (scoretype *)dictGetVal(de);
rank = m_zslGetRank(zsl, score, ele);
if (return_score != NULL) {
*return_score = score;
}
} else {
return -1;
}
Expand All @@ -779,6 +782,8 @@ long exZsetRank(TairZsetObj *zobj, RedisModuleString *ele, int reverse, int bysc

void exZrankGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc, int reverse, int byscore) {
long rank;
int withscore = 0;
scoretype *score = NULL;

RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_READ);
int type = RedisModule_KeyType(key);
Expand All @@ -795,9 +800,31 @@ void exZrankGenericCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int ar
tair_zset_obj = RedisModule_ModuleTypeGetValue(key);
}

rank = exZsetRank(tair_zset_obj, argv[2], reverse, byscore);
if (argc == 4) {
if (mstringcasecmp(argv[3], "withscore")) {
RedisModule_ReplyWithError(ctx, "ERR syntax error");
return;
} else{
withscore = 1;
}
}

if (withscore) {
rank = exZsetRank(tair_zset_obj, argv[2], reverse, byscore, &score);
} else {
rank = exZsetRank(tair_zset_obj, argv[2], reverse, byscore, NULL);
}

if (rank >= 0) {
if (withscore) {
RedisModule_ReplyWithArray(ctx, 2);
}
RedisModule_ReplyWithLongLong(ctx, rank);
if (withscore) {
sds score_str = mscore2String(score);
RedisModule_ReplyWithStringBuffer(ctx, score_str, sdslen(score_str));
m_sdsfree(score_str);
}
} else {
RedisModule_ReplyWithNull(ctx);
}
Expand Down Expand Up @@ -2062,21 +2089,21 @@ int TairZsetTypeZcard_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv
return REDISMODULE_OK;
}

/* EXZRANK key member */
/* EXZRANK key member [WITHSCORE] */
int TairZsetTypeZrank_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
RedisModule_AutoMemory(ctx);
if (argc != 3) {
if (argc < 3 || argc > 4) {
return RedisModule_WrongArity(ctx);
}

exZrankGenericCommand(ctx, argv, argc, 0, 0);
return REDISMODULE_OK;
}

/* EXZREVRANK key member */
/* EXZREVRANK key member [WITHSCORE] */
int TairZsetTypeZrevrank_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
RedisModule_AutoMemory(ctx);
if (argc != 3) {
if (argc < 3 || argc > 4) {
return RedisModule_WrongArity(ctx);
}

Expand Down
33 changes: 12 additions & 21 deletions tests/tairzset.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ start_server {tags {"tairzset"} overrides {bind 0.0.0.0}} {
assert_equal 1 [r exzrevrank tairzsetkey y]
assert_equal 0 [r exzrevrank tairzsetkey z]
assert_equal "" [r exzrevrank tairzsetkey foo]

# withscores
assert_equal {0 10} [r exzrank tairzsetkey x withscore]
assert_equal {1 20} [r exzrank tairzsetkey y withscore]
assert_equal {2 30} [r exzrank tairzsetkey z withscore]
assert_equal "" [r exzrank tairzsetkey foo withscore]
assert_equal {2 10} [r exzrevrank tairzsetkey x withscore]
assert_equal {1 20} [r exzrevrank tairzsetkey y withscore]
assert_equal {0 30} [r exzrevrank tairzsetkey z withscore]
assert_equal "" [r exzrevrank tairzsetkey foo withscore]
}

test "EXZRANKBYSCORE/EXZREVRANKBYSCORE basics" {
Expand All @@ -96,6 +106,8 @@ start_server {tags {"tairzset"} overrides {bind 0.0.0.0}} {
r exzrem tairzsetkey y
assert_equal 0 [r exzrank tairzsetkey x]
assert_equal 1 [r exzrank tairzsetkey z]
assert_equal {0 10} [r exzrank tairzsetkey x withscore]
assert_equal {1 30} [r exzrank tairzsetkey z withscore]
}

test "EXZINCRBY - can create a new sorted set" {
Expand Down Expand Up @@ -365,27 +377,6 @@ start_server {tags {"tairzset"} overrides {bind 0.0.0.0}} {
assert_equal {d 4 c 3 b 2 a 1} [r exzrevrange ztmp 0 -1 withscores]
}

test "EXZRANK/EXZREVRANK basics" {
r del zranktmp
r exzadd zranktmp 10 x
r exzadd zranktmp 20 y
r exzadd zranktmp 30 z
assert_equal 0 [r exzrank zranktmp x]
assert_equal 1 [r exzrank zranktmp y]
assert_equal 2 [r exzrank zranktmp z]
assert_equal "" [r exzrank zranktmp foo]
assert_equal 2 [r exzrevrank zranktmp x]
assert_equal 1 [r exzrevrank zranktmp y]
assert_equal 0 [r exzrevrank zranktmp z]
assert_equal "" [r exzrevrank zranktmp foo]
}

test "EXZRANK - after deletion" {
r exzrem zranktmp y
assert_equal 0 [r exzrank zranktmp x]
assert_equal 1 [r exzrank zranktmp z]
}

test "EXZINCRBY - can create a new sorted set" {
r del zset
r exzincrby zset 1 foo
Expand Down

0 comments on commit 2a7d863

Please sign in to comment.