我们知道redis集合计算差集的命令是 sdiff。那么有序集合的差集是用 zdiff 命令吗?redis api目前是不支持这个命令的。其实有序集合求差集还是有使用场景的。
使用场景例子
有序集合记录了英语兴趣课(key=english)、数学兴趣课(key=math)的学员及成绩。
```
127.0.0.1:6379> zadd english 98 user1 85 user2 88 user3
(integer) 3
127.0.0.1:6379> zadd math 77 user2 69 user4 100 user5
(integer) 3
```
需要计算出只参加了英语兴趣课的学员
解决思路
A)使用集合diff
客户端程序把有序集合的学员数据导入到无序集合,通过集合的diff计算出结果
B)利用有序集合里已有命令
* ZUNIONSTORE 计算并集,并设置并集后元素计分权重
> ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
* ZREMRANGEBYSCORE 去除计分为0的元素
> ZREMRANGEBYSCORE key min max
redis命令实现
```
127.0.0.1:6379> zunionstore result 2 english math weights 1 0 aggregate min
(integer) 5
127.0.0.1:6379> zremrangebyscore result 0 0
(integer) 3
127.0.0.1:6379> zrange result 0 -1
1) "user3"
2) "user1"
```
进一步优化,命令合并
```
redis-zset-diff.lua 文件
local zsetKey1=KEYS[1];
local zsetKey2=KEYS[2];
local zsetKeyResult=ARGV[1];
redis.call("zunionstore", zsetKeyResult, 2, zsetKey1, zsetKey2, "weights", 1, 0, "aggregate", "min");
redis.call("zremrangebyscore", zsetKeyResult, 0, 0);
return redis.call("zrange", zsetKeyResult, 0, -1);
执行命令
~ redis-cli --eval redis-zset-diff.lua english math , result
1) "user3"
2) "user1"
```
或者执行合并的lua脚本
```
127.0.0.1:6379> eval 'local zsetKey1=KEYS[1];local zsetKey2=KEYS[2];local zsetKeyResult=ARGV[1];redis.call("zunionstore", zsetKeyResult, 2, zsetKey1, zsetKey2, "weights", 1, 0, "aggregate", "min");redis.call("zremrangebyscore", zsetKeyResult, 0, 0);return redis.call("zrange", zsetKeyResult, 0, -1);' 2 english math reslut
1) "user3"
2) "user1"
```