使用Redis构建简单的社交网站

文章目录

  • 第1关:创建用户与动态
  • 第2关:处理用户关系
  • 第3关:状态与信息流


第1关:创建用户与动态

编程要求
在Begin-End区域编写 create_user(login_name, real_name) 函数,实现创建新用户的功能,具体参数与要求如下:

方法参数login_name为用户登录名,real_name为用户真名;
用户登录名预处理的实现:将用户登录名转换成全小写格式;
重名检测的实现:查询哈希键users中是否存在与用户登录名同名的域,若存在,则不允许重新创建该用户,返回None;
分配用户编号的实现:对计数器user:id递增1,并将递增后的值作为新用户的编号;
存储用户信息的实现:使用事务一次性提交:
存储登录名的实现:将用户登录名记录到哈希键users当中,值为该用户编号;
存储详情的实现:按照如下示意将用户信息存储到哈希键user:{id}中:

返回创建结果的实现:返回新创建用户的编号。
编写 create_post(uid, content) 函数,实现创建新动态的功能,具体参数与要求如下:

方法参数uid为发布动态的用户编号,content为要发布的动态内容;
用户合法性检测的实现:查找用户编号对应详情信息哈希user:{uid}是否存在login_name域,若存在,则记录,若不存在,则不允许创建新动态,返回None;
分配动态编号的实现:对计数器post:id递增1,并将递增后的值作为新动态的编号;
存储动态信息的实现:按照如下示意将动态信息存储到哈希键post:{id}中:

更新用户动态数的实现:为该用户编号对应的详情信息哈希user:{uid}中的posts域的值加1;
返回创建结果的实现:返回新创建动态的编号。
测试说明
平台会对你编写的代码进行测试:

测试输入:无;
预期输出:

测试 create_user 方法…
第一次创建登录名为 TestUser 的用户
创建的用户ID为: 1
当前分配的用户ID为: 1
创建的用户信息为: {‘login_name’: ‘testuser’, ‘posts’: ‘0’, ‘real_name’: ‘Test User’, ‘followers’: ‘0’, ‘following’: ‘0’, ‘id’: ‘1’}
第二次创建登录名为 TestUser 的用户
创建的用户ID为: None
当前分配的用户ID为: 1
测试 create_post 方法…
为用户 1 创建一条动态
创建的动态ID为: 1
当前分配的动态ID为: 1
创建的动态信息为: {‘content’: ‘First POST!’, ‘uid’: ‘1’, ‘user_name’: ‘testuser’, ‘id’: ‘1’}
对应用户信息中更新为: {‘login_name’: ‘testuser’, ‘posts’: ‘1’, ‘real_name’: ‘Test User’, ‘followers’: ‘0’, ‘following’: ‘0’, ‘id’: ‘1’}
为不存在的用户 9 创建一条动态
创建的动态ID为: None
开始你的任务吧,祝你成功!

#!/usr/bin/env python
#-*- coding:utf-8 -*-import re
import time
import redisconn = redis.Redis()# 创建新用户
def create_user(login_name, real_name):# 请在下面完成要求的功能#********* Begin *********#login_name = login_name.lower()if conn.hget("users", login_name):return Noneuid = conn.incr("user:id")pipe = conn.pipeline(True)pipe.hset("users", login_name, uid)pipe.hmset("user:%i"%(uid), {'login_name': login_name,'id': uid,'real_name': real_name,'followers': 0,'following': 0,'posts': 0,'last_signup': time.time(),})pipe.execute()return uid#********* End *********## 为用户创建新动态
def create_post(uid, content):# 请在下面完成要求的功能#********* Begin *********#pipe = conn.pipeline(True)pipe.hget("user:%i"%(uid), 'login_name')pipe.incr("post:id")login_name, pid = pipe.execute()if not login_name:return Nonepipe.hmset("post:%i"%(pid), {'id': pid,'uid': uid,'content': content,'posted': time.time(),'user_name': login_name,})pipe.hincrby("user:%i"%(uid), 'posts')pipe.execute()return pid#********* End *********#

在这里插入图片描述

第2关:处理用户关系

编程要求
在Begin-End区域编写 follow(uid, other_uid) 函数,实现关注用户的功能,具体参数与要求如下:

方法参数uid为当前用户编号,other_uid为被关注的用户编号;
避免重复关注的实现:如果被关注的用户编号已经在当前用户的关注列表following:{uid}中,则不重复关注,直接返回None;
建立关注关系的实现:使用事务一次性提交:
将被关注的用户编号加入到当前用户的关注列表following:{uid}中,分值为当前时间戳。
将当前用户编号加入到被关注用户的粉丝列表中followers:{other_uid},分值为当前时间戳。
修改统计数据的实现:若关系建立成功,则使用事务一次性提交:
将当前用户详情user:{uid}中的关注数following加1
将被关注用户详情user:{other_uid}中的粉丝数followers加1
返回执行结果的实现:返回True
编写 unfollow(uid, other_uid) 函数,实现取消关注的功能,具体参数与要求如下:

方法参数uid为当前用户编号,other_uid为被取消关注的用户编号;
避免重复取消关注的实现:如果被关注的用户编号已经不在当前用户的关注列表following:{uid}中,则不重复取消关注,直接返回None;
删除关注关系的实现:使用事务一次性提交:
从当前用户的关注列表following:{uid}中移除被取消关注用户编号。
从被取消关注用户的粉丝列表中followers:{other_uid}移除当前用户编号。
修改统计数据的实现:若关系删除成功,则使用事务一次性提交:
将当前用户详情user:{uid}中的关注数following减1
将被取消关注用户详情user:{other_uid}中的粉丝数followers减1
返回执行结果的实现:返回True
注意:
关注列表和粉丝列表均为有序集合,存储成员时,分值均为当前时间戳;
用户详情为上一关中创建的哈希结构。

测试说明
平台会对你编写的代码进行测试:

测试输入:

9
4
预期输出:

测试 follow 方法…
用户 9 关注 用户 4
关注结果: True
用户 9 的关注列表内容为: [‘4’]
用户 4 的粉丝列表内容为: [‘9’]
用户 9 的用户详情为: {‘login_name’: ‘test_user9’, ‘posts’: ‘0’, ‘real_name’: ‘Test user9’, ‘followers’: ‘0’, ‘following’: ‘1’, ‘id’: ‘9’}
用户 4 的用户详情为: {‘login_name’: ‘test_user4’, ‘posts’: ‘0’, ‘real_name’: ‘Test user4’, ‘followers’: ‘1’, ‘following’: ‘0’, ‘id’: ‘4’}
用户 9 再次关注 用户 4
关注结果: None
测试 unfollow 方法…
用户 9 取消关注 用户 4
取消关注结果: True
用户 9 的关注列表内容为: []
用户 4 的粉丝列表内容为: []
用户 9 的用户详情为: {‘login_name’: ‘test_user9’, ‘posts’: ‘0’, ‘real_name’: ‘Test user9’, ‘followers’: ‘0’, ‘following’: ‘0’, ‘id’: ‘9’}
用户 4 的用户详情为: {‘login_name’: ‘test_user4’, ‘posts’: ‘0’, ‘real_name’: ‘Test user4’, ‘followers’: ‘0’, ‘following’: ‘0’, ‘id’: ‘4’}
用户 9 再次取消关注 用户 4
取消关注结果: None
开始你的任务吧,祝你成功!

#!/usr/bin/env python
#-*- coding:utf-8 -*-import re
import time
import redisconn = redis.Redis()# 关注用户
def follow(uid, other_uid):# 请在下面完成要求的功能#********* Begin *********#fkey1 = "following:%s"%(uid)fkey2 = "followers:%s"%(other_uid)if conn.zscore(fkey1, other_uid):return Nonenow = time.time()pipe = conn.pipeline(True)pipe.zadd(fkey1, other_uid, now)pipe.zadd(fkey2, uid, now)following, followers = pipe.execute()pipe.hincrby("user:%s"%(uid), 'following', int(following))pipe.hincrby("user:%s"%(other_uid), 'followers', int(followers))pipe.execute()return True#********* End *********## 取消关注
def unfollow(uid, other_uid):# 请在下面完成要求的功能#********* Begin *********#fkey1 = "following:%s"%(uid)fkey2 = "followers:%s"%(other_uid)if not conn.zscore(fkey1, other_uid):return Nonepipe = conn.pipeline(True)pipe.zrem(fkey1, other_uid)pipe.zrem(fkey2, uid)following, followers = pipe.execute()pipe.hincrby("user:%s"%(uid), 'following', -int(following))pipe.hincrby("user:%s"%(other_uid), 'followers', -int(followers))pipe.execute()return True#********* End *********## 创建新用户
def create_user(login_name, real_name):login_name = login_name.lower()if conn.hget("users", login_name):return Noneuid = conn.incr("user:id")pipe = conn.pipeline(True)pipe.hset("users", login_name, uid)pipe.hmset("user:%i"%(uid), {'login_name': login_name,'id': uid,'real_name': real_name,'followers': 0,'following': 0,'posts': 0,'last_signup': time.time(),})pipe.execute()return uid# 为用户创建新动态
def create_post(uid, content):pipe = conn.pipeline(True)pipe.hget("user:%i"%(uid), 'login_name')pipe.incr("post:id")login_name, pid = pipe.execute()if not login_name:return Nonepipe.hmset("post:%i"%(pid), {'id': pid,'uid': uid,'content': content,'posted': time.time(),'user_name': login_name,})pipe.hincrby("user:%i"%(uid), 'posts')pipe.execute()return pid

在这里插入图片描述

第3关:状态与信息流

编程要求
在Begin-End区域编写 get_home_timeline(uid) 函数,实现获得主页时间线的功能,具体参数与要求如下:

方法参数uid为要获取主页时间线的用户编号;
获取动态编号的实现:从存储用户主页时间线的有序集合home:{uid}中按照分值递减的顺序取出所有成员;
获取动态详情的实现:遍历动态编号,使用事务一次性获取每个动态编号对应动态详情哈希键post:{pid}的所有域-值对;
返回主页时间线的实现:返回事务执行的结果。
编写 post(uid, content) 函数,实现发布动态并将动态推送给粉丝的功能,具体参数与要求如下:

方法参数uid为要发布动态的用户编号,content为要发布的动态内容;
发布动态的实现:调用第一关中实现的create_post方法,并接收返回的动态编号,若发布失败,则取消发布,返回None;
获取发布时间的实现:从新发布的动态编号对应的动态详情哈希键post:{pid}中获取posted域;
更新个人主页的实现:将新发布的动态编号存储到个人主页有序集合键profile:{uid}中,分值为转为浮点数后的发布时间;
更新粉丝主页时间线的实现:遍历用户的粉丝列表followers:{uid},将新发布的动态编号存储到每个粉丝的主页时间线的有序集合home:{follower_id}中,分值为转为浮点数后的发布时间;
返回发布结果的实现:返回新发布的动态编号。
测试说明
平台会对你编写的代码进行测试:

测试输入:4;
预期输出:

用户 4 关注 用户 1
关注结果: True
测试 post 方法…
创建动态: 1
创建动态: 2
用户 1 的动态列表: [‘2’, ‘1’]
用户 4 的主页时间线动态编号: [‘2’, ‘1’]
测试 get_home_timeline 方法…
用户 4 的主页时间线: [{‘content’: ‘NEW post from user 1!!!’, ‘uid’: ‘1’, ‘user_name’: ‘test_user1’, ‘id’: ‘2’}, {‘content’: ‘This is the first post from user 1’, ‘uid’: ‘1’, ‘user_name’: ‘test_user1’, ‘id’: ‘1’}]
开始你的任务吧,祝你成功!

#!/usr/bin/env python
#-*- coding:utf-8 -*-import re
import time
import redisconn = redis.Redis()# 获得主页时间线
def get_home_timeline(uid, page=1, count=30):# 请在下面完成要求的功能#********* Begin *********#post_ids = conn.zrevrange("home:%s"%(uid), 0, -1)pipe = conn.pipeline(True)for pid in post_ids:pipe.hgetall("post:%s"%(pid))return pipe.execute()#********* End *********## 发布动态并将动态推送给粉丝
def post(uid, content):# 请在下面完成要求的功能#********* Begin *********#pid = create_post(uid, content)if not pid:return Noneposted = conn.hget("post:%s"%(pid), "posted")conn.zadd("profile:%s"%(uid), pid, float(posted))followers = conn.zrange("followers:%s"%(uid), 0, -1)pipe = conn.pipeline(False)for follower in followers:pipe.zadd("home:%s"%(follower), pid, float(posted))pipe.execute()return pid#********* End *********## 关注用户
def follow(uid, other_uid):fkey1 = "following:%s"%(uid)fkey2 = "followers:%s"%(other_uid)if conn.zscore(fkey1, other_uid):return Nonenow = time.time()pipe = conn.pipeline(True)pipe.zadd(fkey1, other_uid, now)pipe.zadd(fkey2, uid, now)following, followers = pipe.execute()posts = conn.zrevrange("profile:%s"%(other_uid), 0, 100, withscores=True)if posts:pipe.zadd("home:%s"%(uid), **dict(posts))pipe.hincrby("user:%s"%(uid), 'following', int(following))pipe.hincrby("user:%s"%(other_uid), 'followers', int(followers))pipe.execute()return True# 取消关注
def unfollow(uid, other_uid):fkey1 = "following:%s"%(uid)fkey2 = "followers:%s"%(other_uid)if not conn.zscore(fkey1, other_uid):return Nonepipe = conn.pipeline(True)pipe.zrem(fkey1, other_uid)pipe.zrem(fkey2, uid)following, followers = pipe.execute()posts = conn.zrevrange("profile:%s"%(other_uid), 0, -1)if posts:pipe.zrem("home:%s"%(uid), *posts)pipe.hincrby("user:%s"%(uid), 'following', -int(following))pipe.hincrby("user:%s"%(other_uid), 'followers', -int(followers))pipe.execute()return True# 创建新用户
def create_user(login_name, real_name):login_name = login_name.lower()if conn.hget("users", login_name):return Noneuid = conn.incr("user:id")pipe = conn.pipeline(True)pipe.hset("users", login_name, uid)pipe.hmset("user:%i"%(uid), {'login_name': login_name,'id': uid,'real_name': real_name,'followers': 0,'following': 0,'posts': 0,'last_signup': time.time(),})pipe.execute()return uid# 为用户创建新动态
def create_post(uid, content):pipe = conn.pipeline(True)pipe.hget("user:%i"%(uid), 'login_name')pipe.incr("post:id")login_name, pid = pipe.execute()if not login_name:return Nonepipe.hmset("post:%i"%(pid), {'id': pid,'uid': uid,'content': content,'posted': time.time(),'user_name': login_name,})pipe.hincrby("user:%i"%(uid), 'posts')pipe.execute()return pid

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/226572.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【javascript】npm ERR! cb() never called!

错误 环境 windows 10 nvm node 14.17.0 如何解决 尝试了 5 种方法 1,npm cache clean --force 2, npm cache verify 3, 删掉package-lock.json (然鹅我的这个项目没有这个文件) 4, npm set strict-ssl false 5, 删除node_modules 这五种…

Excel中MATCH和INDEX函数的用法详解,以及Vlookup的数组用法

match函数 目的:查询函数,范围单元格中搜索特定的项,然后返回该项在此区域中的相对位置。 For example:让 match 去【隔壁办公室】找【老张】 Match 回复:【老张】坐在【隔壁办公室】第【四】个座位上 公式:【 mat…

【FPGA/verilog -入门学习7】 条件判断if与分支判断case语句的语法介绍

需求 使用if 和case 产生格雷码 / /*条件判断if与分支判断case语句的语法介绍 需求 使用if 和case 产生格雷码*/ / timescale 1ns/1ps module vlg_design(input [3:0] i_data, output reg [3:0] o_data,output reg [3:0] o_datac);always (*) begin if (4b0000 i_data) o_d…

MySQL数据库 入门

目录 一、MySQL概述 二、MySQL安装 安装数据库 配置数据库 启动停止数据库 客户端连接数据库 三、数据模型 四、SQL 一、MySQL概述 先来讲解三个概念:数据库、数据库管理系统、 SQL 。 而目前主流的关系型数据库管理系统的市场占有率排名如下: …

【从零开始学习--设计模式--代理模式】

返回首页 前言 感谢各位同学的关注与支持,我会一直更新此专题,竭尽所能整理出更为详细的内容分享给大家,但碍于时间及精力有限,代码分享较少,后续会把所有代码示例整理到github,敬请期待。 此章节介绍建…

C语言算法与数据结构,旅游景区地图求最短路径

背景: 本次作业要求完成一个编程项目。请虚构一张旅游景区地图,景区地图包括景点(结点)和道路(边):地图上用字母标注出一些点,表示景点(比如,以点 A、B、C、…

vue2使用wangeditor实现数学公式+富文本编辑器

需求: 做一个带有数学公式的富文本编辑器,在网上看了很多,这个最合适,借鉴了wangEditor富文本编辑器 这里面写的是v3的整合富文本编辑器,我照着上面改成了v2的,本文章主要是实现步骤和错误解决,…

【数据结构】单链表的定义和操作

目录 1.单链表的定义 2.单链表的创建和初始化 3.单链表的插入节点操作 4.单链表的删除节点操作 5.单链表的查找节点操作 6.单链表的更新节点操作 7.完整代码 🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对你有所帮助…

2023-12-16:用go语言,给定整数数组arr,求删除任一元素后, 新数组中长度为k的子数组累加和的最大值。 来自字节。

2023-12-16:用go语言,给定整数数组arr,求删除任一元素后, 新数组中长度为k的子数组累加和的最大值。 来自字节。 答案2023-12-16: 来自左程云。 灵捷3.5 大体步骤如下: 算法 maxSum1 分析&#xff1…

网络时间服务器

本章主要介绍网络时间服务器。 使用chrony配置时间服务器 配置chrony客户端向服务器同步时间 1 时间同步的必要性 一些服务对时间要求非常严格,例如,图所示的由三台服务器搭建的ceph集群。 这三台服务器的时间必须保持一致,如果不一致&#…

杰卡德的故事

三个男人分别是杰卡德距离 杰卡德相似系数和杰卡德系数 杰卡德相似系数和杰卡德距离是互为相反数的。 杰卡德系数和杰卡德距离是不是一回事 感觉是一回事

DevOps搭建(二)-阿里云镜像仓库的使用详解

博主介绍:Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 🍅文末获取源码下载地址🍅 👇🏻 精彩专栏推荐订阅👇🏻…

NVIDIA A100 PCIE 40GB k8s-device-plugin install in kubernetes

文章目录 1. 目标2. 简介2.1 英伟达 A100 技术规格2.2 架构优势2.3 显卡跑分对比2.4 英伟达 A100 与 kubernetes 3. 安装 NVIDIA A100 GPU 40G 硬件4. NVIDIA R450 datacenter driver5. NVIDIA Container Toolkit6. 创建 runtimeclass5. MIG Strategies6. 配置仓库7. 下载镜像8…

Spring cloud - 断路器 Resilience4J

其实文章的标题应该叫 Resilience4J,而不是Spring Cloud Resilience4J,不过由于正在对Spring cloud的一系列组件进行学习,为了统一,就这样吧。 概念区分 首先区分几个概念 Spring cloud 断路器:Spring Cloud的官网对…

02_Web开发基础之JavaScript

Web开发基础之JavaScript 学习目标和内容 1、能够描述Javascript的作用 2、能够使用分支结构if语句逻辑判断 3、能够使用其中一种循环语句 4、能够定义javaScript中的函数 5、能够定义javaScript中的对象 6、能够描述DOM的作用 7、能够通过DOM操作HTML标签元素及其属性 8、能够…

走进暄桐教室 一起观看暄桐同学作品及感受

暄桐是一间传统美学教育教室,创办于2011年,林曦是创办人和授课老师,教授以书法为主的传统文化和技艺,旨在以书法为起点,亲近中国传统之美,以实践和所得,滋养当下生活。其实,暄桐教室…

数据结构与算法—查找算法(线性查找、二分查找、插值查找、斐波那契查找)

查找算法 文章目录 查找算法1. 线性查找算法2. 二分查找算法2.1 二分查找思路分析2.2 应用实例 3. 插值查找3.1 基本原理3.2 应用实例 4. 斐波那契4.1 基本原理4.2 应用实例 5. 查找总结 在java中,常用的查找有四种: 顺序(线性)查找二分查找/折半查找插值…

广州华锐互动:汽车电子线束加工VR仿真培训与实际生产场景相结合,提高培训效果

随着科技的不断发展,虚拟现实(VR)技术已经逐渐渗透到各个领域,为企业和个人带来了前所未有的便利。在汽车制造行业中,线束加工作为一项关键的生产工艺,其质量直接影响到汽车的性能和安全。因此,…

基于中小微企业_个体工商户的信贷评分卡模型和用户画像(论文_专利_银行调研建模使用)

背景介绍 信用贷款是指由银行或其他金融机构向中小微企业和个体工商户提供的一种贷款产品。该贷款的特点是无需提供抵押品或担保,主要依据借款人的信用状况来进行评估和审批。 中小微企业和个体工商户信用贷款的申请流程相对简单,申请人只需要提供个人…

MySQL数据库的基础概念

目录 顾名思义,数据库是用于存储数据的,那这些数据被存储在哪呢? 文件也能存储数据,那在这个基础上,为什么还要搞出一个数据库来存储数据呢? MySQL的客户端登录/退出指令、服务端的启动/关闭指令 数据…