mirror of
https://github.com/fluencelabs/redis
synced 2025-03-30 22:31:03 +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},
|
{"zrangebylex",zrangebylexCommand,-4,"r",0,NULL,1,1,1,0,0},
|
||||||
{"zrevrangebylex",zrevrangebylexCommand,-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},
|
{"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},
|
{"zrevrange",zrevrangeCommand,-4,"r",0,NULL,1,1,1,0,0},
|
||||||
{"zcard",zcardCommand,2,"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},
|
{"zscore",zscoreCommand,3,"r",0,NULL,1,1,1,0,0},
|
||||||
|
@ -1400,6 +1400,7 @@ void zrevrangebyscoreCommand(redisClient *c);
|
|||||||
void zrangebylexCommand(redisClient *c);
|
void zrangebylexCommand(redisClient *c);
|
||||||
void zrevrangebylexCommand(redisClient *c);
|
void zrevrangebylexCommand(redisClient *c);
|
||||||
void zcountCommand(redisClient *c);
|
void zcountCommand(redisClient *c);
|
||||||
|
void zlexcountCommand(redisClient *c);
|
||||||
void zrevrangeCommand(redisClient *c);
|
void zrevrangeCommand(redisClient *c);
|
||||||
void zcardCommand(redisClient *c);
|
void zcardCommand(redisClient *c);
|
||||||
void zremCommand(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);
|
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. */
|
/* This command implements ZRANGEBYLEX, ZREVRANGEBYLEX. */
|
||||||
void genericZrangebylexCommand(redisClient *c, int reverse) {
|
void genericZrangebylexCommand(redisClient *c, int reverse) {
|
||||||
zlexrangespec range;
|
zlexrangespec range;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user