mirror of
https://github.com/fluencelabs/redis
synced 2025-03-16 15:40:49 +00:00
ZLEXCOUNT implemented.
Like ZCOUNT for lexicographical ranges.
This commit is contained in:
parent
cffeafe391
commit
8b5e0b213e
@ -179,6 +179,7 @@ struct redisCommand redisCommandTable[] = {
|
||||
{"zrangebylex",zrangebylexCommand,-4,"r",0,NULL,1,1,1,0,0},
|
||||
{"zrevrangebylex",zrevrangebylexCommand,-4,"r",0,NULL,1,1,1,0,0},
|
||||
{"zcount",zcountCommand,4,"r",0,NULL,1,1,1,0,0},
|
||||
{"zlexcount",zlexcountCommand,4,"r",0,NULL,1,1,1,0,0},
|
||||
{"zrevrange",zrevrangeCommand,-4,"r",0,NULL,1,1,1,0,0},
|
||||
{"zcard",zcardCommand,2,"r",0,NULL,1,1,1,0,0},
|
||||
{"zscore",zscoreCommand,3,"r",0,NULL,1,1,1,0,0},
|
||||
|
@ -1400,6 +1400,7 @@ void zrevrangebyscoreCommand(redisClient *c);
|
||||
void zrangebylexCommand(redisClient *c);
|
||||
void zrevrangebylexCommand(redisClient *c);
|
||||
void zcountCommand(redisClient *c);
|
||||
void zlexcountCommand(redisClient *c);
|
||||
void zrevrangeCommand(redisClient *c);
|
||||
void zcardCommand(redisClient *c);
|
||||
void zremCommand(redisClient *c);
|
||||
|
73
src/t_zset.c
73
src/t_zset.c
@ -2359,6 +2359,79 @@ void zcountCommand(redisClient *c) {
|
||||
addReplyLongLong(c, count);
|
||||
}
|
||||
|
||||
void zlexcountCommand(redisClient *c) {
|
||||
robj *key = c->argv[1];
|
||||
robj *zobj;
|
||||
zlexrangespec range;
|
||||
int count = 0;
|
||||
|
||||
/* Parse the range arguments */
|
||||
if (zslParseLexRange(c->argv[2],c->argv[3],&range) != REDIS_OK) {
|
||||
addReplyError(c,"min or max not valid string range item");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Lookup the sorted set */
|
||||
if ((zobj = lookupKeyReadOrReply(c, key, shared.czero)) == NULL ||
|
||||
checkType(c, zobj, REDIS_ZSET)) return;
|
||||
|
||||
if (zobj->encoding == REDIS_ENCODING_ZIPLIST) {
|
||||
unsigned char *zl = zobj->ptr;
|
||||
unsigned char *eptr, *sptr;
|
||||
|
||||
/* Use the first element in range as the starting point */
|
||||
eptr = zzlFirstInLexRange(zl,range);
|
||||
|
||||
/* No "first" element */
|
||||
if (eptr == NULL) {
|
||||
addReply(c, shared.czero);
|
||||
return;
|
||||
}
|
||||
|
||||
/* First element is in range */
|
||||
sptr = ziplistNext(zl,eptr);
|
||||
redisAssertWithInfo(c,zobj,zzlLexValueLteMax(eptr,&range));
|
||||
|
||||
/* Iterate over elements in range */
|
||||
while (eptr) {
|
||||
/* Abort when the node is no longer in range. */
|
||||
if (!zzlLexValueLteMax(eptr,&range)) {
|
||||
break;
|
||||
} else {
|
||||
count++;
|
||||
zzlNext(zl,&eptr,&sptr);
|
||||
}
|
||||
}
|
||||
} else if (zobj->encoding == REDIS_ENCODING_SKIPLIST) {
|
||||
zset *zs = zobj->ptr;
|
||||
zskiplist *zsl = zs->zsl;
|
||||
zskiplistNode *zn;
|
||||
unsigned long rank;
|
||||
|
||||
/* Find first element in range */
|
||||
zn = zslFirstInLexRange(zsl, range);
|
||||
|
||||
/* Use rank of first element, if any, to determine preliminary count */
|
||||
if (zn != NULL) {
|
||||
rank = zslGetRank(zsl, zn->score, zn->obj);
|
||||
count = (zsl->length - (rank - 1));
|
||||
|
||||
/* Find last element in range */
|
||||
zn = zslLastInLexRange(zsl, range);
|
||||
|
||||
/* Use rank of last element, if any, to determine the actual count */
|
||||
if (zn != NULL) {
|
||||
rank = zslGetRank(zsl, zn->score, zn->obj);
|
||||
count -= (zsl->length - rank);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
redisPanic("Unknown sorted set encoding");
|
||||
}
|
||||
|
||||
addReplyLongLong(c, count);
|
||||
}
|
||||
|
||||
/* This command implements ZRANGEBYLEX, ZREVRANGEBYLEX. */
|
||||
void genericZrangebylexCommand(redisClient *c, int reverse) {
|
||||
zlexrangespec range;
|
||||
|
Loading…
x
Reference in New Issue
Block a user