如何在 Redis 中管理排序集

介绍

Redis是一个开源的,内存中的关键值数据存储。在Redis中, sorted sets是类似于 sets的数据类型,因为它们都是不重复的字符串组。不同之处在于,一个分类集的每个成员都与一个分数有关,允许他们从最小分数到最大分数进行分类。 与集合一样,一个分类集的每个成员必须是独特的,尽管多个成员可以共享相同的分数。

本教程解释了如何创建分类集,检索和删除其成员,并从现有组中创建新的分类集。

如何使用此指南

这个指南是写成一个骗局的表,包含自含的示例,我们鼓励你跳到任何与你试图完成的任务相关的部分。

在本指南中显示的命令在运行 Redis 版本 6.0.1 版本的 Ubuntu 22.04 服务器上进行了测试。 要设置类似的环境,您可以遵循我们指南中的 Step 1How To Install and Secure Redis on Ubuntu 22.04 上进行测试。 我们将通过使用 Redis 命令行接口的 redis-cli 来演示这些命令的行为。 如果您使用不同的 Redis 接口 - 例如 - 某些命令的准确输出可能会有所不同。

或者,您可以提供一个受管理的 Redis 数据库实例来测试这些命令,但取决于数据库提供商允许的控制水平,本指南中的一些命令可能无法按描述的方式工作。 要提供 DigitalOcean 受管理数据库,请遵循我们的 管理数据库产品文档

创建排序集并添加会员

要创建一个排序集,请使用zadd命令。zadd接受作为参数将排序集保留的密钥的名称,然后是您添加的成员的分数和成员本身的值。

1zadd faveGuitarists 1 "Joe Pass"

'zadd' 将返回一个整数,表示如果成功创建该排序集,有多少成员被添加到排序集中:

1[secondary_label Output]
2(integer) 1

请注意,他们的分数不需要连续,分数之间可能存在差距,并且在相同的分类集中持有的多个成员可以共享相同的分数:

1zadd faveGuitarists 4 "Stephen Malkmus" 2 "Rosetta Tharpe" 3 "Bola Sete" 3 "Doug Martsch" 8 "Elizabeth Cotten" 12 "Nancy Wilson" 4 "Memphis Minnie" 12 "Michael Houser"
1[secondary_label Output]
2(integer) 8

「zadd」可以接受以下选项,您必须在键名后和第一个会员分数之前输入:

*「NX」或「XX」:这些选项具有相反的效果,所以你只能在任何「zadd」操作中包括其中一个:

  • 'NX': 告诉 'zadd' **不更新现有成员. 使用此选项, 'zadd' 只会添加新元素。
  • 'XX': 告诉 'zadd' 仅更新现有元素。 使用此选项, 'zadd' 永远不会添加新成员。
  • 'CH': 通常, 'zadd' 只会返回新元素添加到排序集的数量。 但是,包含此选项, 'zadd' 会返回更改元素的数量。 此选项包括新添加的成员和被更改的成员。

而不是将INCR选项转换为zadd,您可以使用zincrby命令,该命令以完全相同的方式行事。而不是将zadd等分数值指定的值给排序组成员,它会将该成员的分数增加到该值。

1zincrby faveGuitarists 5 "Stephen Malkmus"
1[secondary_label Output]
2"9"

zadd命令的INCR选项一样,如果指定的成员不存在,那么zincrby将创建它以增量值作为其分数。

回收来自分类的集合的成员

获取分类集中的成员的最基本方法是使用zrange命令. 此命令接受作为参数你想要获取的成员的密钥的名称和其中包含的成员的范围。

下面的示例将返回上一节创建的faveGuitarists排序集中的前四个成员:

1zrange faveGuitarists 0 3
1[secondary_label Output]
21) "Joe Pass"
32) "Rosetta Tharpe"
43) "Bola Sete"
54) "Doug Martsch"

请注意,如果您转到zrange的排序集有两个或多个共享相同分数的元素,则将以 lexicographical 或字母顺序排序这些元素。

开始和停止指数也可以是负数,‘-1’代表最后一个成员,‘-2’代表第二个最后一个成员,等等:

1zrange faveGuitarists -5 -2
1[secondary_label Output]
21) "Memphis Minnie"
32) "Elizabeth Cotten"
43) "Stephen Malkmus"
54) "Michael Houser"

'zrange' 可以接受 'WITHSCORES' 参数,其中包含时也会返回成员的分数:

1zrange faveGuitarists 5 6 WITHSCORES
1[secondary_label Output]
21) "Elizabeth Cotten"
32) "8"
43) "Stephen Malkmus"
54) "9"

「zrevrange」只能返回一系列成員以上升的數字順序。 要逆轉這項順序,並返回一系列成員以下降的順序,你必須使用「zrevrange」命令。 想想這個命令是暫時逆轉該特定排序集的順序,然後返回屬於指定範圍的成員。

1zrevrange faveGuitarists 0 5
1[secondary_label Output]
21) "Nancy Wilson"
32) "Michael Houser"
43) "Stephen Malkmus"
54) "Elizabeth Cotten"
65) "Memphis Minnie"
76) "Doug Martsch"

zrevrange也可以接受WITHSCORES选项。

您可以使用zrangebyscore命令返回基于他们的分数的成员范围. 在下面的示例中,该命令将返回任何持有faveGuitarists键的成员,分数为 2, 3 或 4:

1zrangebyscore faveGuitarists 2 4
1[secondary_label Output]
21) "Rosetta Tharpe"
32) "Bola Sete"
43) "Doug Martsch"
54) "Memphis Minnie"

该范围在本示例中是包括的,这意味着它会返回有 2 或 4 分的成员,您可以通过以开放的标注(()来排除该范围的任何一个结尾:下面的示例会返回每个得分大于或等于 2',但小于 4 的成员:

1zrangebyscore faveGuitarists 2 (4
1[secondary_label Output]
21) "Rosetta Tharpe"
32) "Bola Sete"
43) "Doug Martsch"

zrangebyscore一样,zrangebyscore 可以接受WITHSCORES参数,它还可以接受LIMIT选项,您可以使用它来从zrangebyscore输出中仅获取一个选项选项。此选项接受一个 offset,该选项标记了命令返回的范围中的第一个成员,以及一个计数,该选项定义了命令返回的成员总数。例如,下面的命令会审查faveGuitarists排列组的第一个六个成员,但只会从该组中返回三个成员,从该范围中的第二个成员返回,表示为1:

1zrangebyscore faveGuitarists 0 5 LIMIT 1 3
1[secondary_label Output]
21) "Rosetta Tharpe"
32) "Bola Sete"
43) "Doug Martsch"

zrevrangebyscore命令会根据他们的分数返回一个反向的成员范围。

1zrevrangebyscore faveGuitarists 10 6
1[secondary_label Output]
21) "Stephen Malkmus"
32) "Elizabeth Cotten"

zrangebyscore一样,zrevrangebyscore可以接受WITHSCORESLIMIT选项,此外,您可以通过以开放的标注来排除该范围的任何一端。

在这种情况下,你可以强迫 Redis 以zrangebylex命令返回一个以字母顺序排序的元素范围,或者按字母顺序返回一个以字母顺序排序的元素范围。

1zadd SomervilleSquares 0 Davis 0 Inman 0 Union 0 porter 0 magoun 0 ball 0 assembly

zrangebylex必须由一个键的名称、一个开始间隔和一个停止间隔接着。

1zrangebylex SomervilleSquares [a [z
1[secondary_label Output]
21) "assembly"
32) "ball"
43) "magoun"
54) "porter"

请注意,本示例只返回了集中的八个成员中的四个,尽管命令搜索了从az的范围,这是因为Redis值是案例敏感的,所以从其输出中排除了以上级字母开头的成员。

1zrangebylex SomervilleSquares [A [z
1[secondary_label Output]
21) "Davis"
32) "Inman"
43) "Union"
54) "assembly"
65) "ball"
76) "magoun"
87) "porter"

zrangebylex也接受代表负无限的特殊字符-+,代表正无限的特殊字符,因此,下面的命令语法也将返回排序集的每个成员:

1zrangebylex SomervilleSquares - +

请注意,zrangebylex不能以反向语法(升起的字母)顺序返回排序的集合成员,请使用zrevrangebylex:

1zrevrangebylex SomervilleSquares + -
1[secondary_label Output]
21) "porter"
32) "magoun"
43) "ball"
54) "assembly"
65) "Union"
76) "Inman"
87) "Davis"

因为它是用来使用与排序的集,每个成员都有相同的分数,所以zrangebylex不接受WITHSCORES选项,但它不接受LIMIT选项。

获取有关 Sorted Sets 的信息

要找出某一特定排序集中的成员数(换句话说,要确定其 cardinality),请使用zcard命令。

1zcard faveGuitarists
1[secondary_label Output]
2(integer) 9

'zcount' 可以告诉你在一个特定的排序集中包含多少元素,这些元素属于一个分数范围. 接着键的第一个数字是范围的开始,第二个是范围的结束:

1zcount faveGuitarists 3 8
1[secondary_label Output]
2(integer) 4

'zscore' 输出一个分类集的特定成员的分数:

1zscore faveGuitarists "Bola Sete"
1[secondary_label Output]
2"3"

如果指定的成员或密钥不存在,则zscore将返回(nil)

zrank类似于zscore,但不是返回给定的会员的分数,而是返回其分数。在Redis中,一个 _rank_是排序组成员的基于零的索引,按他们的分数排序。

1zrank faveGuitarists "Joe Pass"
1[secondary_label Output]
2(integer) 0

有另一个名为zrevrank的Redis命令,该命令执行与zrank相同的函数,但取而代之地扭转了集中的成员的行列。

1zrevrank faveGuitarists "Joe Pass"
1[secondary_label Output]
2(integer) 8

会员的分数和他们的分数之间的唯一关系是他们的分数与其他会员的分数相比。如果有两个连续会员之间的分数差距,这不会反映在他们的分数中。

zscore,zrankzrevrank将返回(nil),如果密钥或成员不存在。

zlexcount 可以告诉你在一个词汇范围之间进行排序的集合中有多少成员。

1zlexcount SomervilleSquares [M [t
1[secondary_label Output]
2(integer) 5

此命令跟zrangebylex命令相同的语法,因此请参阅 上一节 有关如何定义字符串范围的详细信息。

从排序集中删除会员

zrem命令可以从排序集中删除一个或多个成员:

1zrem faveGuitarists "Doug Martsch" "Bola Sete"

zrem将返回一个整数,表示它从排序集中删除了多少成员:

1[secondary_label Output]
2(integer) 2

有三个Redis命令,允许您根据范围删除分类集的成员.例如,如果分类集中的每个成员都有相同的分数,您可以使用zremrangebylex删除基于语法范围的成员。

1zremrangebylex SomervilleSquares [A [Z

zremrangebylex将输出一个整数,表示它删除了多少成员:

1[secondary_label Output]
2(integer) 3

您也可以使用zremrangebyscore命令根據數字範圍刪除會員,該命令使用與zrangebyscore命令相同的語法。

1zremrangebyscore faveGuitarists 4 6
1[secondary_label Output]
2(integer) 1

您可以使用zremrangebyrank命令从基于一系列的行列中删除成员,该命令使用与zrangebyrank相同的语法。

1zremrangebyrank faveGuitarists 0 2
1[secondary_label Output]
2(integer) 3

请注意,转到remrangebyrank的数字也可能为负数,而-1代表最高等级,-2代表下一个最高等级,等等。

创建新的分类集从现有集合中

Redis 包含两个命令,允许您比较多个分类集的成员,并根据这些比较创建新的命令: zinterstorezunionstore. 若要使用这些命令进行实验,请运行以下 zadd 命令来创建一些示例分类集:

1zadd NewKids 1 "Jonathan" 2 "Jordan" 3 "Joey" 4 "Donnie" 5 "Danny"
2zadd Nsync 1 "Justin" 2 "Chris" 3 "Joey" 4 "Lance" 5 "JC"

「zinterstore」會找到由兩個或多個分類集合共享的成員 - 他們的交叉 - 並生成一個新的分類集合,其中只包含這些成員。

1zinterstore BoyBands 2 NewKids Nsync

由于NewKidsNsync只共享一个成员,即Joey,该命令将返回1:

1[secondary_label Output]
2(integer) 1

请注意,如果目标密钥已经存在,zinterstore将重写其内容。

这个命令使用与zinterstore相同的语法,并需要目标密钥的名称,传递到命令的密钥的数量,以及密钥的名称:

1zunionstore SuperGroup 2 NewKids Nsync

zinterstore一样,zunionstore会返回一个整数,显示存储在目标密钥中的元素数量. 尽管原始排序集有五个成员,因为排序集不能有重复的成员,并且每个密钥都有一个名为Joey的成员,结果的整数将是9:

1[secondary_label Output]
2(integer) 9

zinterstore一样,zunionstore将重写目标密钥的内容,如果它已经存在。

为了让您在使用zinterstorezunionstore创建新排序集时对会员分数进行更大的控制,这两个命令都接受WIGHTSAGGREGATE选项。

重量选项随后为命令中包含的每一个排序集添加一个号码,该号码重量或倍增每个成员的分数.在重量选项之后的第一个号码重量了传给命令的第一个键的分数,第二个号码重量了第二个键,等等。

下面的示例创建了一个新的排序集,其中包含来自NewKidsNsync排序集的交叉键。

1zinterstore BoyBandsWeighted 2 NewKids Nsync WEIGHTS 3 7

如果重量选项不包含,则对zinterstorezunionstore的重量默认为1

「AGGREGATE」接受三個子選項,其中第一個「SUM」實施「zinterstore」和「zunionstore」的默認行為,將相匹配成員的得分添加到組合中。

如果您在共享一个成员的两个分类集上运行zinterstorezunionstore操作,但该成员在每个集中都有不同的分数,则可以强迫该操作使用MIN子选项在新集中的两个分数中分配较低的分数:

1zinterstore BoyBandsWeightedMin 2 NewKids Nsync WEIGHTS 3 7 AGGREGATE MIN

由于两个排序集只有一个与相同分数(3)相匹配的成员,因此这个命令将创建一个新的集,其中一个成员有两个重量分数中较低的分数:

1zscore BoyBandsWeightedMin "Joey"
1[secondary_label Output]
2"9"

同样,AGGREGATE可以强迫zinterstorezunionstoreMAX选项分配两个分数中更高的分数:

1zinterstore BoyBandsWeightedMax 2 NewKids Nsync WEIGHTS 3 7 AGGREGATE MAX

此命令会创建一个新的集合,其中一个成员是Joey,其中有两个重量级得分中的较高得分:

1zscore BoyBandsWeightedMax "Joey"
1[secondary_label Output]
2"21"

同样,将汇总选项考虑为决定如何控制会员的分数,然后他们被添加到他们的新集。

结论

本指南详细介绍了一些用于在 Redis 中创建和管理排序集的命令. 如果在本指南中您想要了解的其他相关命令、论点或程序,请在评论中询问或提出建议。

有关 Redis 命令的更多信息,请参阅我们的教程系列 如何管理 Redis 数据库

Published At
Categories with 技术
comments powered by Disqus