Redis入门--头歌实验初始redis

打印 上一主题 下一主题

主题 574|帖子 574|积分 1726

一、Redis中的数据结构

   任务描述

  本关任务:启动 Redis 客户端并创建一些值。
  相关知识

  为了完本钱关任务,你需要把握:1.Redis简介,2.快速安装Redis与Python,3.Redis数据结构简介。
  Redis简介

  Redis 是一个速度非常快的非关系型数据库(non-relational database),它可以存储键(key)和五种不同类型的值(value)之间的映射(mapping),可基于内存存储亦可持久化到硬盘的日志型,Key-Value 数据库。
  Redis与其他数据库的对比

  如果你利用过关系型数据库,比方:Mysql,那么你肯定写过关联两张表数据的查询语句。而 Redis 属于 NoSQL,它不利用表,也不会预界说数据模式或强制用户对 Redis 的各种数据进行关联。
     NoSQL(Not Only SQL)
       意指“不仅仅是SQL”,其泛指非关系型数据库,主要分为四类:键值(Key-Value)存储数据库,列存储数据库,文档型数据库,图形(Graph)数据库。
    Redis 也经常与高性能键值缓存服务器 memcached 做比较:两者均可用于存储键值映射,性能相差也甚少,但 Redis 能存储除平凡字符串值之外的四种数据结构,而 memcached 只能存储平凡的字符串值。这些不同使得 Redis 能够解决更为广泛的题目,而且既能作为主数据库利用,也可以作为辅助数据库利用。
  
  0我们通过一张表来对比常用的数据库与缓存服务器:
  名称类型数据存储选项查询类型附加功能Redis基于内存的非关系型数据库字符串、列表、集合、哈希、有序集合针对数据类型有专属命令,另有批量利用和不完全的事件支持发布与订阅、复制、持久化、脚本扩展memcached基于内存的键值缓存键值映射创建、读取、更新、删除等多线程支持MySQL关系型数据库数据表、视图等查询、插入、更新、删除、内置函数、自界说存储过程等支持 ACID 性质、复制等MongoDB基于硬盘的非关系型文档存储数据库无 schema 的 BSON 文档创建、读取、更新、删除、条件查询等复制、分片、空间索引等  Redis的特性

  由于 Redis 是内存型数据库,在利用之前就要考虑当服务器被关闭时,服务器存储的数据是否能保留。Redis 拥有两种不同情势的持久化方法,都可以用紧凑的格式将数据写入硬盘:
  

  • RDB 持久化

    • 在指定的时间间隔内生成数据集的时间点快照

  • AOF 持久化

    • 记载服务器实验的全部写利用命令
    • 新命令会被追加到文件的末尾
    • 在服务器启动时,通过重新实验这些命令还原数据集

  除此之外,为了扩展 Redis 的读性能,并为 Redis 提供故障转移支持,Redis 实现了主从复制特性:
  

  • 实验复制的从服务器毗连主服务器

    • 汲取主服务器发送的初始副本
    • 汲取主服务器实验的全部写命令

  • 在从服务器上实验全部写命令,实时更新数据库
  • 读命令可以向恣意一个从服务器发送
  快速安装 Redis 

  docker-compose部署redis
  
  Redis数据结构简介

  Redis 的五种数据结构分别是:
  

  • 字符串(STRING)
  • 列表(LIST)
  • 集合(SET)
  • 哈希(HASH)
  • 有序集合(ZSET)
  ZSET 可以说是 Redis 特有的数据结构,我们会在之后的实训中详细介绍它,在本实训中,我们只扼要介绍他们的功能和小部分命令。他们的存储的值如下:
  结构类型存储的值STRING字符串、整数或浮点数LIST一个链表,上面的每个节点都是一个字符串SET包罗若干个字符串的无序集合,且集合中的元素都是唯一的HASH包罗键值对的无序散列表ZSET成员中的字符串与分值的有序映射,其排序由分值决定  在安装完 Redis 并启动了 redis-server 后,我们可以利用 redis-cli 控制台与 Redis 进行交互,其启动方式是在终端中输入:
  redis-cli
  其会默认毗连本机 6379 端口启动的 Redis 服务器,接下俩你可以利用它来体验 Redis 各种数据结构和其命令的利用。
  
  Redis中的字符串

  STRING 拥有一些和其他键值存储相似的命令,比如 GET(获取值),SET(设置值),DEL(删除值)等,比方:
  
  1. $ redis-cli
  2. redis-cli 127.0.0.1:6379> set hello redis
  3. OK
  4. redis-cli 127.0.0.1:6379> get hello
  5. "redis"
  6. redis-cli 127.0.0.1:6379> del hello
  7. (integer) 1
  8. redis-cli 127.0.0.1:6379> get hello
  9. (nil)
复制代码
其中:
  

  • SET 命令的第一个参数是键(Key),第二个参数是值(Value)
  • 实验获取不存在的键时会得到一个 nil
  Redis中的列表

  就像前面所说的,Redis 中的列表是一个“链表”,这和大多数编程语言相似。以是他们的利用也非常相似:
  

  • LPUSH 命令可用于将元素推入列表的左侧
  • RPUSH 命令可将元素推入列表的右侧
  • LPOP 和 RPOP 就分别从列表的左侧和右侧弹出元素
  • LINDEX 可以获取指定位置上的元素
  • LRANGE 可以获取指定范围的全部元素
  我们通过 redis-cli 来亲自体验:
  
  1. redis 127.0.0.1:6379> rpush testlist item
  2. (integer) 1
  3. redis 127.0.0.1:6379> rpush testlist item2
  4. (integer) 2
  5. redis 127.0.0.1:6379> rpush testlist item
  6. (integer) 3
  7. redis 127.0.0.1:6379> lrange testlist 0 -1
  8. 1) "item"
  9. 2) "item2"
  10. 3) "item"
  11. redis 127.0.0.1:6379> lindex testlist 1
  12. "item2"
  13. redis 127.0.0.1:6379> lpop testlist
  14. "item"
  15. redis 127.0.0.1:6379> lrange testlist 0 -1
  16. 1) "item2"
  17. 2) "item"
复制代码
我们可以看出,在列表中,元素可以重复出现。在后续的实训中,我们还会介绍更多列表命令,现在我们先来了解以下 Redis 中的集合。
  
  Redis中的集合

  集合和列表的区别就在于:列表可以存储多个相同的字符串,而集合通过散列表来保证存储的字符串都是各不相同的(这些散列表只有键,而没有对应的值)。
  
  由于集合是无序的,以是我们只能通过统一的 SADD 命令将元素添加到集合中,SREM 命令将元素从集合中移除。你还可以通过:
  

  • SMEMBERS 命令获取到集合中的全部元素
  • SISMEMBER 命令来判断一个元素是否已存在在集合中
  1. redis 127.0.0.1:6379> sadd testset item
  2. (integer) 1
  3. redis 127.0.0.1:6379> sadd testset item2
  4. (integer) 1
  5. redis 127.0.0.1:6379> sadd testset item
  6. (integer) 0
  7. redis 127.0.0.1:6379> smembers testset
  8. 1) "item"
  9. 2) "item2"
  10. redis 127.0.0.1:6379> sismember testset item3
  11. (integer) 0
  12. redis 127.0.0.1:6379> sismember testset item
  13. (integer) 1
  14. redis 127.0.0.1:6379> srem testset item2
  15. (integer) 1
  16. redis 127.0.0.1:6379> srem testset item2
  17. (integer) 0
  18. redis 127.0.0.1:6379>  smembers testset
  19. 1) "item"
复制代码
上面示例的集合中包罗的元素少,以是实验 SMEMBERS 命令没有题目,一旦集合中包罗的元素非常多时,SMEMBERS 命令的实验速度会很慢,以是要谨慎的利用这个命令。
  
  Redis中的哈希

  哈希可以存储多个键值对之间的映射。和字符串一样,哈希存储的值既可以是字符串又可以是数字值,并且可以对数字值进行自增/自减利用。
  哈希就像是一个缩小版的 Redis,有一系列命令对哈希进行插入、获取、删除:
  

  • HSET key field value:设置哈希字段的值
  • HGET key field:获取哈希字段的值
  • HDEL key field:删除哈希字段
  • HEXISTS key field:查抄哈希字段是否存在
  • HKEYS key:获取哈希的全部字段
  • HVALS key:获取哈希的全部值
  • HGETALL key:获取哈希的全部字段和值
  • HLEN key:获取哈希的字段数量
  • HMSET key field1 value1 [field2 value2 ]:设置多个哈希字段
  • HMGET key field1 [field2]:获取多个哈希字段的
  1. redis 127.0.0.1:6379> hset testhash key1 value1
  2. (integer) 1
  3. redis 127.0.0.1:6379> hset testhash key2 value2
  4. (integer) 1
  5. redis 127.0.0.1:6379> hset testhash key1 newvalue
  6. (integer) 0
  7. redis 127.0.0.1:6379> hgetall testhash
  8. 1) "key1"
  9. 2) "newvalue"
  10. 3) "key2"
  11. 4) "value2"
  12. redis 127.0.0.1:6379> hdel testhash key2
  13. (integer) 1
  14. redis 127.0.0.1:6379> hget testhash key1
  15. "newvalue"
  16. redis 127.0.0.1:6379> hgetall testhash
  17. 1) "key1"
  18. 2) "newvalue"
复制代码
其中:
  

  • hset 用于插入元素

    • 第一个参数为该哈希的键名,如果该哈希不存在,则创建一个
    • 第二个参数为哈希中的域名

      • 如果不存在,则创建该域,并与第三个参数的值进行映射


  • 如果存在,则利用第三个参数更新该域的值

    • 第三个参数为哈希中的值

  • hgetall 会获取到该哈希的全部域-值对
  • hget 用于获取哈希中的某一个域
  • hdel 用户删除哈希中的某一个域
  Redis中的有序集合

  有序集合和哈希一样,也是存储键值对。
  只是有序集合的键被称为成员(member),每个成员都是唯一的,有序集合的值则被称为分值(score),这个分值必须为浮点数。以是有序集合既可以通过成员访问元素,也可以通过分值来排序元素。
  
  我们可以通过:
  

  • ZADD 命令将带有指定分值的成员添加到有序集合中
  • ZRANGE 命令根据分值有序排列后的集合获取到指定范围的元素
  • ZRANGEBYSCORE 命令获取指定分值范围内的元素
  • ZREM 命令从有序集合中删除指定成员
  1. redis 127.0.0.1:6379> zadd testzset 100 member1
  2. (integer) 1
  3. redis 127.0.0.1:6379> zadd testzset 200 member0
  4. (integer) 1
  5. redis 127.0.0.1:6379> zrange testzset 0 -1 withscores
  6. 1) "member1"
  7. 2) "100"
  8. 3) "member0"
  9. 4) "200"
  10. redis 127.0.0.1:6379> zrangebyscore testzset 0 150 withscores
  11. 1) "member1"
  12. 2) "100"
  13. redis 127.0.0.1:6379> zrem testzset member1
  14. (integer) 1
  15. redis 127.0.0.1:6379> zrange testzset 0 -1 withscores
  16. 1) "member0"
  17. 2) "200"
复制代码
编程要求

  根据提示,打开命令行,启动 Redis 客户端并创建一些值:
  

  • 利用默认配置后台启动 Redis 服务器
  • 启动 Redis 客户端 redis-cli
  • 设置字符串

    • 键为 hello
    • 值为 redis

  • 设置列表,键为 educoder-list

    • 从列表左侧推入元素 hello
    • 从列表右侧推入元素 educoder
    • 从列表右侧推入元素 bye
    • 从列表右侧弹出一个元素

  • 设置集合,键为 educoder-set

    • 添加元素 c
    • 添加元素 python
    • 添加元素 redis
    • 删除元素 c

  • 设置哈希,键为 educoder-hash

    • 添加键:python,值为:language
    • 添加键:ruby,值为:language
    • 添加键: redis,值为:database
    • 删除键 ruby

  • 设置有序列表,键为 educoder-zset

    • 添加成员 jack,分值为 200
    • 添加成员 rose,分值为 400
    • 添加成员 lee,分值为 100

  1. redis-cli
  2. set hello redis
  3. LPUSH educoder-list hello
  4. RPUSH educoder-list educoder
  5. RPUSH educoder-list bye
  6. RPOP educoder-list
  7. sadd educoder-set c
  8. sadd educoder-set python
  9. sadd educoder-set redis
  10. srem educoder-set c
  11. hset educoder-hash python language
  12. hset educoder-hash ruby language
  13. hset educoder-hash redis database
  14. hdel educoder-hash ruby
  15. zadd educoder-zset 200 jack
  16. zadd educoder-zset 400 rose
  17. zadd educoder-zset 100 lee
复制代码
二、利用 Python 与 Redis 交互

   任务描述

  本关任务:利用 Python 编写程序与 Redis 交互。
  相关知识

  为了完本钱关任务,你需要把握:1.怎样利用 Python 毗连 Redis,2.通过客户端对 Redis 的数据进行利用。
  怎样利用 Python 毗连 Redis

  如果你在上一关中已经利用 easy_install 包安装了 redis 包,那么你现在毗连 Redis 就很简朴了,可以利用以下两种方法:
  
  方法1:
  1. # 导入 redis 模块
  2. import redis
  3. # 创建 redis 客户端
  4. conn = redis.Redis()
  5. ...
  6. # 使用完资源之后删除客户端 conn
  7. del conn
复制代码
方法2:
  
  1. # 导入 redis 模块
  2. import redis
  3. # 创建连接池
  4. pool = redis.ConnectionPool(host='127.0.0.1', port=6379, decode_responses=True)
  5. # 创建客户端并连接到 Redis
  6. r = redis.Redis(connection_pool=pool)
复制代码
两种方法的对比如下:
  

  • 方法 1:需要在利用完该客户端后手动删除客户端,以制止创建多个毗连
  • 方法 2:

    • 利用了毗连池总揽多个客户端与服务端的毗连
    • 不需要手动删除客户端
    • 同时有效的减少多个客户端毗连的损耗

  以是我们在现实开辟中利用第二种方法较多。
  在创建了客户端之后,你就可以利用 coon 或 r 这个客户端来进行 Redis 利用了。
  通过客户端对 Redis 的数据进行利用

  通过客户端对 Redis 的数据进行利用和第一关直接在 Redis 中的利用命令基本相同。只是在客户端中利用如下,要在命令前加上客户端的名字和.(假设利用方法2创建客户端r):
  1. # 使用 SET 命令设置一个字符串键
  2. r.set("test", "hello")
  3. # 显示字符串键 test 的值
  4. print(r.get("test"))
复制代码
编程要求

  根据提示,在右侧Begin-End区域增补代码,实现利用 Python 编写程序与 Redis 交互:
  

  • 利用方法2创建客户端r1毗连到 Redis 
  • 设置下表中的两个字符串键:
  键值test1hellotest2Redis
  1. #!/usr/bin/env python
  2. #-*- coding:utf-8 -*-
  3. import redis
  4. def write_redis():
  5.     #********* Begin *********#
  6.     r1 = redis.Redis(host='localhost', port=6379, db=0)
  7.     # 设置键值对
  8.     r1.set('test1', 'hello')
  9.     r1.set('test2', 'Redis')
  10.     #********* End *********#
复制代码
三、利用Python+Redis实现文章投票网站后端功能

   任务描述

  本关任务:编写一个简化版文章投票网站的后端处置惩罚逻辑。
  相关知识

  第一关中,我们对 Redis 提供的五种数据结构有了基本的了解,这一关我们学习怎样利用这些数据结构来解决现实题目。
  大多数网站都提供了对新闻、文章大概问答进行投票的功能,并根据文章的发布时间/投票数量进行排序。本关卡中,我们将利用 Redis 构建简朴的文字投票及排序功能。
  为了完本钱关任务,你需要把握:1.实现投票功能,2.创建文章数据,3.对文章进行排序。
  实现投票功能

  实现投票功能,要注意文章的时效性与投票的公平性,以是需要给投票功能加上一些约束条件:
  

  • 文章发布满一个星期后,不再允许用户对该文章投票
  • 一个用户对一篇文章只能投一次票
  以是我们需要利用:
  

  • 一个有序集合 time,存储文章的发布时间
  • 一个集合 voted:*,存储已投票用户名单

    • 其中 * 是被投票文章的 ID

  • 一个有序集合 score,存储文章的得票数
  1. # 定义一个常量,表示一周的秒数
  2. ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60
  3. # 定义一个函数,处理用户对文章的投票
  4. def article_vote(r, user_id, article_id):
  5.     # 使用 time.time() 获取当前时间
  6.     # 减去一周的秒数,从而获取一周前的Unix时间
  7.     cutoff = time.time() - ONE_WEEK_IN_SECONDS
  8.     # 检查文章的发布时间是否在一周前
  9.     # 如果是,那么不允许投票,直接返回
  10.     if r.zscore('time', article_id) < cutoff:
  11.         return
  12.     # 尝试将用户添加到已经投票的用户集合中
  13.     # 如果用户是第一次投票,那么 sadd 方法会返回 1
  14.     # 如果用户已经投过票,那么 sadd 方法会返回 0
  15.     if r.sadd('voted:' + article_id, user_id):
  16.         # 如果用户是第一次投票,那么增加文章的得分
  17.         r.zincrby('score', article_id, 1)
复制代码
在这段代码中,我们利用了Redis的有序集合(zset)和集合(set)数据类型。zscore方法用于获取有序集合中元素的分数,sadd方法用于向集合中添加元素,zincrby方法用于增长有序集合中元素的分数
  
  当用户实验投票时,利用 ZSCORE 命令读取 time 有序集合,得到这篇文章的发布时间,再判断文章的发布时间是否凌驾一周。ZSCORE 命令的语法如下:
  r.zscore(key, member)
  

  • key :是有序集合的键名
  • member :是有序集合中的某个成员
  若未凌驾,则利用 SADD 命令实验将用户追加到这篇文章的已投票用户名单中,如果添加成功,则说明该用户未投过票。SADD 命令的语法是:
  r.sadd(key, member)
  

  • key :是集合的键名
  • member :是要添加进集合的元素
  由于集合中的元素是唯一的,以是sadd函数会根据member是否存在在集合中做出不同返回:
  

  • 若该元素不存在在集合中,返回 True
  • 若该元素已存在在集合中,返回 False
  以是返回为 True 时利用 ZINCRBY 命令来为文章的投票数加 1。
  
  zincrby 函数语法如下:
  r.zincrby(key, member, increment)
  

  • key :是有序集合的键名
  • member :是有序集合中要增长分值的成员
  • increment :是要增长的分值
  创建文章数据

  现在系统中还缺少文章数据,以是我们要提供一个创建文章的函数,并把文章数据存储到 Redis 中。创建文章的步骤如下:
  

  • 创建新的文章 ID
  • 将文章作者加入到这篇文章的已投票用户名单中
  • 存储文章详细信息到 Redis 中
  • 将文章的发布时间和初始投票数加入到 time 和 score 两个有序集合中
  r.expire(key, seconds)
  

  • key :要设置过期时间的键名
  • seconds :过期时间的长度(单元:秒)
  这里我们要设置的时间是一周,以是我们可以利用上面界说好的全局变量 ONE_WEEK_IN_SECONDS。
  在这段代码中,我们利用了Redis的字符串(string)、集合(set)、哈希(hash)和有序集合(zset)数据类型。incr命令用于对字符串值进行自增利用,sadd命令用于向集合中添加元素,expire命令用于设置键的过期时间,hmset命令用于向哈希中添加多个字段和值,zadd命令用于向有序集合中添加元素。
  
  将文章作者加入已投票用户名单中和之前一样,这里不再赘述,但在这里我们需要为这个已投票用户名单设置一个过期时间,让它在一周后(到期后)主动删除,减少 Redis 的内存斲丧。为设置过期时间的命令是:
  
  r.expire(key, seconds)
  

  • key :要设置过期时间的键名
  • seconds :过期时间的长度(单元:秒)
  这里我们要设置的时间是一周,以是我们可以利用上面界说好的全局变量 ONE_WEEK_IN_SECONDS。
  
  接下来要存储文章详细信息了,前面介绍过 hset 可以实验单个字段(域)的设置,这里我们利用 hmset 一次性设置多个字段(域),其语法如下:
  r.hmset(key, {field: value, [field: value ...]})
  
  我们可以利用 Python 的散列来一次性存储多个字段(域)到 Redis,只需要将整个散列看成 key 对应的值通过 hmset 函数设置进去就行。
  最后,将初始投票数和创建时间设置到 score 和 time 中都可以通过 ZADD 命令来实现:
  
  我们可以利用 Python 的散列来一次性存储多个字段(域)到 Redis,只需要将整个散列看成 key 对应的值通过 hmset 函数设置进去就行。
  最后,将初始投票数和创建时间设置到 score 和 time 中都可以通过 ZADD 命令来实现:
  r.zadd(key, member, score)
  

  • key :有序集合的键名
  • member :要加入有序集合的成员
  • score :该成员的分值
  这里需要注意的是,因为该篇文章的作者已经被加入到该文章已投票用户名单中,为了保持数据同等性,我们需要将文章的初始投票数设为 1。
  
  对文章进行排序

  实现了文章投票和创建文章功能,接下来我们就需要将评分最高的文章最新发布的文章从 Redis 中取出了。
  

  • 首先我们要根据排序方式的不同:

    • 按评分排序,则从 score 有序集合中取出一定量的文章 ID(score有序集合存放文章ID和对应的投票数)
    • 按时间排序,则从 time 有序集合中取出一定量的文章 ID(time有序集合存放文章ID和对应的发布时间)

  • 构成一个有序文章信息列表,每个元素都:

    • 利用 HGETALL 命令,取出每篇文章的全部信息

  1. def get_articles(r, start, end, order='score'):
  2.     # 使用Redis的ZREVRANGE命令获取有序集合中的一系列元素。这些元素是按照分数从高到低排序的,范围是从start到end
  3.     ids = r.zrevrange(order, start, end)
  4.     # 创建一个空列表,用于存储获取到的文章
  5.     articles = []
  6.     # 遍历获取到的元素ID
  7.     for id in ids:
  8.         # 使用Redis的HGETALL命令获取哈希中的所有字段和值,这些字段和值构成了文章的数据
  9.         article_data = r.hgetall(id)
  10.         # 将元素ID添加到文章数据中
  11.         article_data['id'] = id
  12.         # 将文章数据添加到列表中
  13.         articles.append(article_data)
  14.     # 返回文章列表
  15.     return articles
复制代码
这里因为需要对有序集合进行排序,以是我们在取出文章 ID 时需要利用到 ZREVRANGE 命令,以分值从大到小的排序方式取出文章 ID。ZREVRANGE 命令的语法是:
  r.zrevrange(key, start, stop)
  

  • key :有序集合的键名
  • start :开始的数组下标
  • stop :竣事的数组下标
  得到多个文章 ID 后,我们还需要根据每一个文章 ID 获取文章的全部信息,这时就需要利用到 HGETALL 命令,它的语法如下:
  r.hgetall(key)
  

  • key :哈希的键名
  我们取出文章的全部信息后,还为文章信息添加了一个字段 id。这是因为文章 ID 在 Redis 中是作为键名存储的,不在值当中,以是我们需要附加这个字段到文章信息中。
  实现这些方法后,我们大体实现了一个文章投票的后端处置惩罚逻辑,能够为文章投票并能根据投票结果改变文章的排序环境。
  
  编程要求

  根据提示,在右侧Begin-End区域增补代码,完成简化版文章投票网站的后端处置惩罚逻辑:
  

  • 在 article_vote() 函数中:

    • 该方法作用是:对文章投票
    • 参数说明:

      • r:Redis 客户端


  • user_id:投票用户
  • article_id:被投票文章

    • 已提供一周前 Unix 时间戳,存放在变量 cutoff
    • 当满意以下条件时,为文章投一票:

      • 该文章发布不凌驾一周


  • 该用户没有为该文章投过票
  • 在 post_article() 函数中:

    • 该方法作用是:创建文章
    • 参数说明:

      • r:Redis 客户端


  • user:发布用户
  • title:文章标题
  • link:文章链接

    • 已提供:

      • article_id,新文章 ID


  • voted,新文章已投票用户名单存储键名
  • article,新文章详细信息存储键名
  • now,文章创建时间

    • 按照 ID 递增的顺序依次创建文章
    • 保证发布文章的用户不能给自己的文章投票
    • 文章在发布一周后删除已投票用户名单
    • 存储文章详细信息到 Redis 中,包罗字段:

      • 文章标题


  • 文章链接
  • 发布用户

    • 存储文章的发布时间和初始投票数

      • 初始投票数为 1


  • 在 get_articles() 函数中:

    • 该方法作用是:对文章进行排序
    • 参数说明:

      • r:Redis 客户端
      • start:从排序为 start 的文章开始获取


  • end:到排序为 end 的文章竣事获取
  • order:排序方式,分为两种:

    • time:按时间排序
    • score:按投票数排序

  • 已提供文章信息空列表,articles
  • 实现按时间/投票数排序
  • 将排序后的文章及其全部信息组成一个列表:

    • 按照不同排序规则取出排序在参数提供的区间范围内的文章
    • 及每篇文章的全部信息,包罗文章 ID

  1. #!/usr/bin/env python
  2. #-*- coding:utf-8 -*-
  3. import time
  4. ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60
  5. def article_vote(r, user_id, article_id):
  6.     cutoff = time.time() - ONE_WEEK_IN_SECONDS
  7.     # 请在下面完成要求的功能
  8.     #********* Begin *********#
  9.     if r.zscore('time', article_id) < cutoff:
  10.         return
  11.     if r.sadd('voted:' + article_id, user_id):
  12.         r.zincrby('score', article_id, 1)
  13.     #********* End *********#
  14. def post_article(r, user, title, link):
  15.     article_id = str(r.incr('article'))
  16.     voted = 'voted:' + article_id
  17.     now = time.time()
  18.     article = 'article:' + article_id
  19.     # 将发布文章的用户添加到投票集合中,并设置投票集合的过期时间为一周
  20.     r.sadd(voted, user)
  21.     r.expire(voted, ONE_WEEK_IN_SECONDS)
  22.     # 将文章的标题、链接和发布者添加到哈希中,并将文章添加到得分和时间有序集合中
  23.     r.hmset(article, {
  24.         'title': title,
  25.         'link': link,
  26.         'poster': user,
  27.     })
  28.     r.zadd('score', article_id, 1)
  29.     r.zadd('time', article_id, now)
  30.     return article_id
  31. def get_articles(r, start, end, order='score'):
  32.     articles = []
  33.     # 请在下面完成要求的功能
  34.     #********* Begin *********#
  35.     ids = r.zrevrange(order, start, end)
  36.     for id in ids:
  37.         article_data = r.hgetall(id)
  38.         article_data['id'] = id
  39.         articles.append(article_data)
  40.     #********* End *********#
  41.     return articles
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王國慶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表