Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
hanoi2005
redis
提交
d2764cd6
R
redis
项目概览
hanoi2005
/
redis
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
redis
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
d2764cd6
编写于
3月 13, 2010
作者:
P
Pieter Noordhuis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
added explicit AGGREGATE [SUM|MIN|MAX] option to ZUNION/ZINTER
上级
164ee595
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
68 addition
and
22 deletion
+68
-22
redis.c
redis.c
+52
-22
test-redis.tcl
test-redis.tcl
+16
-0
未找到文件。
redis.c
浏览文件 @
d2764cd6
...
@@ -5387,8 +5387,26 @@ static int qsortCompareZsetopsrcByCardinality(const void *s1, const void *s2) {
...
@@ -5387,8 +5387,26 @@ static int qsortCompareZsetopsrcByCardinality(const void *s1, const void *s2) {
return
size1
-
size2
;
return
size1
-
size2
;
}
}
#define REDIS_AGGR_SUM 1
#define REDIS_AGGR_MIN 2
#define REDIS_AGGR_MAX 3
inline
static
void
zunionInterAggregate
(
double
*
target
,
double
val
,
int
aggregate
)
{
if
(
aggregate
==
REDIS_AGGR_SUM
)
{
*
target
=
*
target
+
val
;
}
else
if
(
aggregate
==
REDIS_AGGR_MIN
)
{
*
target
=
val
<
*
target
?
val
:
*
target
;
}
else
if
(
aggregate
==
REDIS_AGGR_MAX
)
{
*
target
=
val
>
*
target
?
val
:
*
target
;
}
else
{
/* safety net */
redisAssert
(
0
!=
0
);
}
}
static
void
zunionInterGenericCommand
(
redisClient
*
c
,
robj
*
dstkey
,
int
op
)
{
static
void
zunionInterGenericCommand
(
redisClient
*
c
,
robj
*
dstkey
,
int
op
)
{
int
i
,
j
,
zsetnum
;
int
i
,
j
,
zsetnum
;
int
aggregate
=
REDIS_AGGR_SUM
;
zsetopsrc
*
src
;
zsetopsrc
*
src
;
robj
*
dstobj
;
robj
*
dstobj
;
zset
*
dstzset
;
zset
*
dstzset
;
...
@@ -5429,19 +5447,28 @@ static void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
...
@@ -5429,19 +5447,28 @@ static void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
/* parse optional extra arguments */
/* parse optional extra arguments */
if
(
j
<
c
->
argc
)
{
if
(
j
<
c
->
argc
)
{
int
remaining
=
c
->
argc
-
j
;
int
remaining
=
c
->
argc
-
j
;
while
(
remaining
)
{
while
(
remaining
)
{
if
(
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"weights"
))
{
if
(
remaining
>=
(
zsetnum
+
1
)
&&
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"weights"
))
{
j
++
;
remaining
--
;
j
++
;
remaining
--
;
if
(
remaining
<
zsetnum
)
{
zfree
(
src
);
addReplySds
(
c
,
sdsnew
(
"-ERR not enough weights for ZUNION/ZINTER
\r\n
"
));
return
;
}
for
(
i
=
0
;
i
<
zsetnum
;
i
++
,
j
++
,
remaining
--
)
{
for
(
i
=
0
;
i
<
zsetnum
;
i
++
,
j
++
,
remaining
--
)
{
src
[
i
].
weight
=
strtod
(
c
->
argv
[
j
]
->
ptr
,
NULL
);
src
[
i
].
weight
=
strtod
(
c
->
argv
[
j
]
->
ptr
,
NULL
);
}
}
}
else
if
(
remaining
>=
2
&&
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"aggregate"
))
{
j
++
;
remaining
--
;
if
(
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"sum"
))
{
aggregate
=
REDIS_AGGR_SUM
;
}
else
if
(
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"min"
))
{
aggregate
=
REDIS_AGGR_MIN
;
}
else
if
(
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"max"
))
{
aggregate
=
REDIS_AGGR_MAX
;
}
else
{
zfree
(
src
);
addReply
(
c
,
shared
.
syntaxerr
);
return
;
}
j
++
;
remaining
--
;
}
else
{
}
else
{
zfree
(
src
);
zfree
(
src
);
addReply
(
c
,
shared
.
syntaxerr
);
addReply
(
c
,
shared
.
syntaxerr
);
...
@@ -5450,27 +5477,28 @@ static void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
...
@@ -5450,27 +5477,28 @@ static void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
}
}
}
}
/* sort sets from the smallest to largest, this will improve our
* algorithm's performance */
qsort
(
src
,
zsetnum
,
sizeof
(
zsetopsrc
),
qsortCompareZsetopsrcByCardinality
);
dstobj
=
createZsetObject
();
dstobj
=
createZsetObject
();
dstzset
=
dstobj
->
ptr
;
dstzset
=
dstobj
->
ptr
;
if
(
op
==
REDIS_OP_INTER
)
{
if
(
op
==
REDIS_OP_INTER
)
{
/* sort sets from the smallest to largest, this will improve our
* algorithm's performance */
qsort
(
src
,
zsetnum
,
sizeof
(
zsetopsrc
),
qsortCompareZsetopsrcByCardinality
);
/* skip going over all entries if the smallest zset is NULL or empty */
/* skip going over all entries if the smallest zset is NULL or empty */
if
(
src
[
0
].
dict
&&
dictSize
(
src
[
0
].
dict
)
>
0
)
{
if
(
src
[
0
].
dict
&&
dictSize
(
src
[
0
].
dict
)
>
0
)
{
/* precondition: as src[0].dict is non-empty and the zsets are ordered
/* precondition: as src[0].dict is non-empty and the zsets are ordered
* from small to large, all src[i > 0].dict are non-empty too */
* from small to large, all src[i > 0].dict are non-empty too */
di
=
dictGetIterator
(
src
[
0
].
dict
);
di
=
dictGetIterator
(
src
[
0
].
dict
);
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
double
*
score
=
zmalloc
(
sizeof
(
double
));
double
*
score
=
zmalloc
(
sizeof
(
double
))
,
value
;
*
score
=
0
.
0
;
*
score
=
src
[
0
].
weight
*
(
*
(
double
*
)
dictGetEntryVal
(
de
))
;
for
(
j
=
0
;
j
<
zsetnum
;
j
++
)
{
for
(
j
=
1
;
j
<
zsetnum
;
j
++
)
{
dictEntry
*
other
=
(
j
==
0
)
?
de
:
dictFind
(
src
[
j
].
dict
,
dictGetEntryKey
(
de
));
dictEntry
*
other
=
dictFind
(
src
[
j
].
dict
,
dictGetEntryKey
(
de
));
if
(
other
)
{
if
(
other
)
{
*
score
=
*
score
+
src
[
j
].
weight
*
(
*
(
double
*
)
dictGetEntryVal
(
other
));
value
=
src
[
j
].
weight
*
(
*
(
double
*
)
dictGetEntryVal
(
other
));
zunionInterAggregate
(
score
,
value
,
aggregate
);
}
else
{
}
else
{
break
;
break
;
}
}
...
@@ -5498,14 +5526,16 @@ static void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
...
@@ -5498,14 +5526,16 @@ static void zunionInterGenericCommand(redisClient *c, robj *dstkey, int op) {
/* skip key when already processed */
/* skip key when already processed */
if
(
dictFind
(
dstzset
->
dict
,
dictGetEntryKey
(
de
))
!=
NULL
)
continue
;
if
(
dictFind
(
dstzset
->
dict
,
dictGetEntryKey
(
de
))
!=
NULL
)
continue
;
double
*
score
=
zmalloc
(
sizeof
(
double
));
double
*
score
=
zmalloc
(
sizeof
(
double
)),
value
;
*
score
=
0
.
0
;
*
score
=
src
[
i
].
weight
*
(
*
(
double
*
)
dictGetEntryVal
(
de
));
for
(
j
=
0
;
j
<
zsetnum
;
j
++
)
{
if
(
!
src
[
j
].
dict
)
continue
;
dictEntry
*
other
=
(
i
==
j
)
?
de
:
dictFind
(
src
[
j
].
dict
,
dictGetEntryKey
(
de
));
/* because the zsets are sorted by size, its only possible
* for sets at larger indices to hold this entry */
for
(
j
=
(
i
+
1
);
j
<
zsetnum
;
j
++
)
{
dictEntry
*
other
=
dictFind
(
src
[
j
].
dict
,
dictGetEntryKey
(
de
));
if
(
other
)
{
if
(
other
)
{
*
score
=
*
score
+
src
[
j
].
weight
*
(
*
(
double
*
)
dictGetEntryVal
(
other
));
value
=
src
[
j
].
weight
*
(
*
(
double
*
)
dictGetEntryVal
(
other
));
zunionInterAggregate
(
score
,
value
,
aggregate
);
}
}
}
}
...
...
test-redis.tcl
浏览文件 @
d2764cd6
...
@@ -1491,6 +1491,14 @@ proc main {server port} {
...
@@ -1491,6 +1491,14 @@ proc main {server port} {
list
[
$r
zunion zsetc 2 zseta zsetb weights 2 3
]
[
$r
zrange zsetc 0 -1 withscores
]
list
[
$r
zunion zsetc 2 zseta zsetb weights 2 3
]
[
$r
zrange zsetc 0 -1 withscores
]
}
{
4
{
a 2 b 7 d 9 c 12
}}
}
{
4
{
a 2 b 7 d 9 c 12
}}
test
{
ZUNION with AGGREGATE MIN
}
{
list
[
$r
zunion zsetc 2 zseta zsetb aggregate min
]
[
$r
zrange zsetc 0 -1 withscores
]
}
{
4
{
a 1 b 1 c 2 d 3
}}
test
{
ZUNION with AGGREGATE MAX
}
{
list
[
$r
zunion zsetc 2 zseta zsetb aggregate max
]
[
$r
zrange zsetc 0 -1 withscores
]
}
{
4
{
a 1 b 2 c 3 d 3
}}
test
{
ZINTER basics
}
{
test
{
ZINTER basics
}
{
list
[
$r
zinter zsetc 2 zseta zsetb
]
[
$r
zrange zsetc 0 -1 withscores
]
list
[
$r
zinter zsetc 2 zseta zsetb
]
[
$r
zrange zsetc 0 -1 withscores
]
}
{
2
{
b 3 c 5
}}
}
{
2
{
b 3 c 5
}}
...
@@ -1499,6 +1507,14 @@ proc main {server port} {
...
@@ -1499,6 +1507,14 @@ proc main {server port} {
list
[
$r
zinter zsetc 2 zseta zsetb weights 2 3
]
[
$r
zrange zsetc 0 -1 withscores
]
list
[
$r
zinter zsetc 2 zseta zsetb weights 2 3
]
[
$r
zrange zsetc 0 -1 withscores
]
}
{
2
{
b 7 c 12
}}
}
{
2
{
b 7 c 12
}}
test
{
ZINTER with AGGREGATE MIN
}
{
list
[
$r
zinter zsetc 2 zseta zsetb aggregate min
]
[
$r
zrange zsetc 0 -1 withscores
]
}
{
2
{
b 1 c 2
}}
test
{
ZINTER with AGGREGATE MAX
}
{
list
[
$r
zinter zsetc 2 zseta zsetb aggregate max
]
[
$r
zrange zsetc 0 -1 withscores
]
}
{
2
{
b 2 c 3
}}
test
{
SORT against sorted sets
}
{
test
{
SORT against sorted sets
}
{
$r del zset
$r del zset
$r zadd zset 1 a
$r zadd zset 1 a
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录