如何在Redis中通过另一个排序集更新排序集?
我是Redis的新手,现在如果密钥存在于另一个排序集中,我需要更新排序集 我认为通过一个例子来解释可能更清楚,假设有两个排序集,如下所示:如何在Redis中通过另一个排序集更新排序集?,redis,jedis,Redis,Jedis,我是Redis的新手,现在如果密钥存在于另一个排序集中,我需要更新排序集 我认为通过一个例子来解释可能更清楚,假设有两个排序集,如下所示: set_1 {key_1:val_1, key_2:val_2, key_3:val_3} set_2 {key_1:val_new_1, key_3:val_new_3, key_4:val_new_4} 现在,如果第二个集合中存在密钥,我将尝试更新第一个集合,因此结果应该是: set_1 {key_1:val_new_1, key_2:val_2,
set_1
{key_1:val_1, key_2:val_2, key_3:val_3}
set_2
{key_1:val_new_1, key_3:val_new_3, key_4:val_new_4}
现在,如果第二个集合中存在密钥,我将尝试更新第一个集合,因此结果应该是:
set_1
{key_1:val_new_1, key_2:val_2, key_3:val_new_3}
我阅读Redis文档已经有一段时间了,使用带有XX选项的SET命令可能会有所帮助:
SET命令支持修改其行为的一组选项:
XX——仅当密钥已存在时设置该密钥
但是,是否可以避免在第一组中的每个条目上运行此操作?可能使用zunionstore?之类的命令,
SET
命令仅适用于常规键,而不适用于排序集
在排序集中,您有分数成员对,因此示例中的键值对命名法有点混乱。我假设key_1,key_2,key_3,…
是成员,val_1,val_2,…
是分数
让我们按如下方式创建排序集以查看解决方案:
> ZADD set_1 1 key_1 2 key_2 3 key_3
(integer) 3
> ZADD set_2 1001 key_1 1003 key_3 1004 key_4
(integer) 3
默认的AGGREGATE
是SUM
,这是我们将在整个系统中使用的
我们将创建两个具有两者交集的排序集,一个分数为set_1
,另一个分数为set_2
> ZINTERSTORE intersect_set_1 2 set_1 set_2 WEIGHTS 1 0
(integer) 2
> ZINTERSTORE intersect_set_2 2 set_1 set_2 WEIGHTS 0 1
(integer) 2
现在,我们为set_1
创建一个中间步骤集,其中set_2
中的那些步骤的分数也设置为零:
> ZUNIONSTORE pre_set_1 2 set_1 intersect_set_1 WEIGHTS 1 -1
(integer) 3
现在,我们已经准备好更新集合_1,进行以下并集:
:所有pre_set_1
,但也将设置_1
设置为零分李>中的设置_2
:intersect\u set\u 2
和set\u 1
的交点,分数为set\u 2
set\u 2
> ZUNIONSTORE set_1 2 pre_set_1 intersect_set_2
(integer) 3
让我们看看结果:
> ZRANGE set_1 0 -1 WITHSCORES
1) "key_2"
2) "2"
3) "key_1"
4) "1001"
5) "key_3"
6) "1003"
别忘了清理:
> UNLINK pre_set_1 intersect_set_1 intersect_set_2
此解决方案不是最优的,因为它使用多个中间步骤,中间添加到原始集合的成员存在风险,并且它使用的内存超过了需要的内存
最佳解决方案是:
这将循环通过set_2
,更新set_1
。请注意在ZADD
命令中使用XX
,以仅更新(如果存在)
用作:
EVAL "local set2 = redis.call('ZRANGE', KEYS[1], '0', '-1', 'WITHSCORES') \n local set2length = table.getn(set2) \n for i=1,set2length,2 do print(1) redis.call('ZADD', KEYS[2], 'XX', set2[i+1], set2[i]) end \n return set2length/2" 2 set_2 set_1
由于Redis的单线程特性,Lua脚本是原子的。SET命令仅适用于常规键,而不适用于排序集 在排序集中,您有分数成员对,因此示例中的键值对命名法有点混乱。我假设
key_1,key_2,key_3,…
是成员,val_1,val_2,…
是分数
让我们按如下方式创建排序集以查看解决方案:
> ZADD set_1 1 key_1 2 key_2 3 key_3
(integer) 3
> ZADD set_2 1001 key_1 1003 key_3 1004 key_4
(integer) 3
默认的AGGREGATE
是SUM
,这是我们将在整个系统中使用的
我们将创建两个具有两者交集的排序集,一个分数为set_1
,另一个分数为set_2
> ZINTERSTORE intersect_set_1 2 set_1 set_2 WEIGHTS 1 0
(integer) 2
> ZINTERSTORE intersect_set_2 2 set_1 set_2 WEIGHTS 0 1
(integer) 2
现在,我们为set_1
创建一个中间步骤集,其中set_2
中的那些步骤的分数也设置为零:
> ZUNIONSTORE pre_set_1 2 set_1 intersect_set_1 WEIGHTS 1 -1
(integer) 3
现在,我们已经准备好更新集合_1,进行以下并集:
:所有pre_set_1
,但也将设置_1
设置为零分李>中的设置_2
:intersect\u set\u 2
和set\u 1
的交点,分数为set\u 2
set\u 2
> ZUNIONSTORE set_1 2 pre_set_1 intersect_set_2
(integer) 3
让我们看看结果:
> ZRANGE set_1 0 -1 WITHSCORES
1) "key_2"
2) "2"
3) "key_1"
4) "1001"
5) "key_3"
6) "1003"
别忘了清理:
> UNLINK pre_set_1 intersect_set_1 intersect_set_2
此解决方案不是最优的,因为它使用多个中间步骤,中间添加到原始集合的成员存在风险,并且它使用的内存超过了需要的内存
最佳解决方案是:
这将循环通过set_2
,更新set_1
。请注意在ZADD
命令中使用XX
,以仅更新(如果存在)
用作:
EVAL "local set2 = redis.call('ZRANGE', KEYS[1], '0', '-1', 'WITHSCORES') \n local set2length = table.getn(set2) \n for i=1,set2length,2 do print(1) redis.call('ZADD', KEYS[2], 'XX', set2[i+1], set2[i]) end \n return set2length/2" 2 set_2 set_1
由于Redis的单线程特性,Lua脚本是原子的