@@ -141,16 +141,108 @@ class RankingList:
141141 ZREVRANGEBYSCORE sorted_set max min
142142 ```
143143 命令的 min 参数和 max 参数分别用于指定用户想要获取的最小分值和最大分值, 要注意这两条命令接受最大最小值的顺序正好相反.
144- 该命令也可以使用 WITHSCORES 参数来同时获取成员及其分值
144+
145+ - 该命令也可以使用 WITHSCORES 参数来同时获取成员及其分值
145146 ```
146147 ZRANGEBYSCORE sorted_set min max [WITHSCORES]
147148 ZREVRANGEBYSCORE sorted_set max min [WITHSCORES]
148149 ```
149- 默认情况下, 该命令会返回范围内的所有成员, 有时成员数量很多, 就可以使用 LIMIT 选项来限制命令返回的成员数量.
150+ - 默认情况下, 该命令会返回范围内的所有成员, 有时成员数量很多, 就可以使用 LIMIT 选项来限制命令返回的成员数量.
150151 ```
151152 ZRANGEBYSCORE sorted_set min max [LIMIT offset count]
152153 ZREVRANGEBYSCORE sorted_set min max [LIMIT offset count]
153154 ```
154155 其中, offset 是指从满足 min 和 max 的元素中, 跳过前面的 offset 个元素, count 是从 offset 之后开始, 返回接下来的 count 个元素.
155156
157+ - 如果要使用开区间而不是闭区间, 在分词的前面加上一个分括号
158+ ```
159+ ZRANGEBYSCORE salary (3500 (5000 WITHSCORES
160+ ```
161+ 这样会返回分值大于3500, 小于5000的成员.
162+
163+ - 最后, 还可以使用无限值作为分值范围
164+ ```
165+ ZRANGEBYSCORE salary -inf (5000 WITHSCORES
166+ ```
167+ 复杂度: O(log(N) + M), N 为有序集和的成员数量, M 为命令返回的成员数量
168+
169+ - ZCOUNT: 统计指定分词范围内的成员数量
170+ ```
171+ ZCOUNT sorted_set min max
172+ ```
173+ 复杂度: O(N)
174+
175+ ### 示例: 时间线
176+ 在互联网上, 很多网站都会根据发布的内容来对时间进行排序:
177+ - 博客系统按照文章发布时间的先后, 将最近发布的文章放在前面
178+ - 新闻网站会按照新闻的发布时间, 把最新的新闻放在网站前面
179+
180+ 类似的情形还有很多, 通过对这类行为进行抽象, 写出下面的时间线程序:
181+ - 把被添加到时间线里的元素用作成员, 与元素相关的时间戳用作分值, 将元素和时间戳添加到集和中
182+ - 将时间线中的元素按照时间戳的大小排序
183+ - 通过对时间线中的元素执行 ZREVRANGE 或者 ZREVRANGEBYSCORE 命令, 用户可以通过分页的方式取出时间线中的元素, 或者从时间线中取出指定时间区间内的元素
184+
185+ ```Python
186+ class Timeline:
187+ def __init__(self, client, key):
188+ self.client = client
189+ self.key = key
190+
191+ def add(self, item, time):
192+ """将元素添加到时间线中"""
193+ self.client.zadd(self.key, {item: time})
194+
195+ def remove(self, item):
196+ """将元素从时间线中移除"""
197+ self.client.zrem(self.key, item)
198+
199+ def count(self):
200+ """返回时间线包含的元素数量"""
201+ return self.client.zcard(self.key)
202+
203+ def pagging(self, number, count, with_time=False):
204+ """
205+ 按照每页 count 个元素, 取出时间线第 number 页上的所有元素, 将元素按照时间戳逆序排序
206+ with_time 表示是否返回时间信息
207+ """
208+ start_index = (number - 1) * count
209+ end_index = number * count - 1
210+ return self.client.zrevrange(self.key, start_index, end_index, with_time)
211+
212+ def fetch_by_time_range(self, min_time, max_time, number, count, with_time=False):
213+ """
214+ 按照每页 count 个元素, 取出时间线第 number 页上的所有元素, 按照时间戳逆序排序
215+ with_time 表示是否返回时间信息
216+ """
217+ start_index = (number - 1) * count
218+ end_index = start_index + count - 1
219+ return self.client.zrevrangebyscore(self.key, max_time, min_time, start_index, end_index, withscores=with_time)
220+ ```
221+
222+ - ZREMRANGEBYRANK: 移除指定排名范围内的成员
223+ ```
224+ ZREMRANGEBYRANK sorted_set start end
225+ ```
226+ 该命令可以从升序排列的有序集和中移除位于指定排名范围内的成员, 然后返回被移除成员的数量
227+ start-\>end 可以是正数, 也可以使用负数 end-\>start
228+
229+ - ZUNIONSTORE、ZINTERSTORE: 有序集和的并集运算和交集运算
230+ ```
231+ ZUNIONSTORE destination numbers sorted_set [sorted_set ...]
232+ ZINTERSOTRE destination numbers sorted_set [sorted_set ...]
233+ ```
234+ 其中, numbers 用于指定参与计算的有序集和数量, 计算结果会存储到 destination 参数指定的键中, 最后返回计算结果包含的成员数量作为返回值
235+ - 此外, 还可以决定使用什么方法来获得集和成员的分值:
236+ ```
237+ ZUNIONSTORE destination numbers sorted_set [sorted_set ...] [AGGREGATE SUM|MIN|MAX]
238+ ZINTERSTORE destination numbers sorted_set [sorted_set ...] [AGGREGATE SUM|MIN|MAX]
239+ ```
240+
241+ - 如果上面的聚合函数不够用, 还可以为每个集和设置权重
242+ ```
243+ ZUNIONSTORE destination numbers sorted_set [sorted ...] [WEIGHTS weight [weight ...]]
244+ ```
245+ 复杂度: ZUNIONSTORE - O(N * log(N)), ZINTERSTORE - O(N * log(N) * M)
246+
156247
248+ 还有很多其他关于有序集和的内容, 这里就不再讨论了.
0 commit comments