gpt4 book ai didi

redis - 如何通过 Redis 中的另一个排序集更新排序集?

转载 作者:行者123 更新时间:2023-12-03 06:45:20 25 4
gpt4 key购买 nike

我是 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}

现在,如果 key 存在于第二组中,我正在尝试更新第一组,因此结果应该是:
set_1
{key_1:val_new_1, key_2:val_2, key_3:val_new_3}

我一直在阅读 Redis 文档,似乎使用带有 XX 选项的 SET 命令可能会有所帮助:

The SET command supports a set of options that modify its behavior: XX -- Only set the key if it already exist.



但是是否有可能避免在第一组的每个条目上运行它?也许使用像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

默认 AGGREGATESUM ,这是我们将使用的所有东西。

我们将创建两个具有交集的排序集,其中一个的分数为 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

现在我们准备更新 set_1,合并:
  • pre_set_1 : 全部 set_1但那些也在 set_2设置为零分。
  • intersect_set_2 : set_1 的交集和 set_2 , 得分为 set_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

    此解决方案不是最优的,因为它使用多个中间步骤,存在将成员添加到中间的原始集合的风险,并且它使用的内存超出了必要的范围。

    最佳解决方案是 Lua script :
    local set2 = redis.call('ZRANGE', KEYS[1], '0', '-1', 'WITHSCORES')
    local set2length = table.getn(set2)
    for i=1,set2length,2 do redis.call('ZADD', KEYS[2], 'XX', set2[i+1], set2[i]) end
    return set2length/2

    这循环通过 set_2 , 更新 set_1 .注意 XX 的使用在 ZADD命令,到 仅限 如果存在则更新。

    用于:
    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 脚本是原子的。

    关于redis - 如何通过 Redis 中的另一个排序集更新排序集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60190262/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com