使用python+redis实现文章发布,投票,分组排名功能

1.逻辑

  实例来源于<<Redis实战>>这本书。

  构建一个投票网站,为这个网站设置一些数值和限制条件:如果一篇文章获得至少200张支持票,那么网站就认为这篇文章是用户喜欢的文章;假如这个网站发布1000篇文章,而其中50篇符合网站对有趣文章的要求,那么网站要把这50篇网站放到首页推荐前100位至少一天。为了产生一个能够随时间流逝而不断减少的评分,程序需要根据文章的发布时间和当前的时间来计算文章的评分,具体计算方法:将文章得到的支持票数乘以一个常量,然后加上文章的发布时间,得出的结果就是文章的评分。

  文章发布时间使用Unix时间戳表示,计算评分时, 与支持票数量相乘的变量为432,这个常量是通过将一天的秒数(86400)除以文章展示一天所需的票数(200)得出的,文章没获得一张支持票,程序就需将文章的评分增加432分。

  

2.实现代码

 #-*- coding: UTF-8 -*- 
import redis
import time

ONE_WEEK_IN_SECONDS = 604800
VOTE_SCORE          = 240.00

pool  = redis.ConnectionPool(host = "127.0.0.1", port = 6379, password = '')
redis = redis.Redis(connection_pool = pool)

#发布文章
def post(articleData, redis = redis):
        articleId = str(redis.incr('article:'))

        '#保存文章'
        article = 'article:' + articleId
        redis.hmset(article,  mapping = articleData)

        '#将文章与发布时间通过一个有序集合进行关联'
        redis.zadd('time',article, articleData['time'])

        '#为自己投初始票'
        vote(article, articleData['poster']) 

        '修改文章评分'
        score(article, redis)
        
        return article

#为文章投票
def vote(article, user, redis = redis):
        global ONE_WEEK_IN_SECONDS
        '#投票,和用户绑定'
        voted       = 'voted:' + article.partition(':')[-1]
        articleData = redis.hgetall(article)
        postTime    = redis.zscore('time', article);

        #一周之前的文章不能投票
        tempTime = time.time() - ONE_WEEK_IN_SECONDS;
        if postTime and postTime <= tempTime:
                return False

        #一个用户只能投一票,判断用户是否已经投过

        if (redis.sismember(voted, user)):
                return False
        
        redis.sadd(voted, articleData[b'poster'])
        redis.expire(voted, ONE_WEEK_IN_SECONDS)

#更新章的评分      
def score(article, redis = redis):
        global VOTE_SCORE
        
        '#将文章与评分通过一个有序集合进行关联'
        redis.zincrby('score', article, VOTE_SCORE)
        redis.hincrby(article, 'votes', 1)

#按特定的方式(发布时间,评分)降序取出文章
def get_articles(order, page = 1, limit = 25, redis = redis):
        start       = (page - 1) * limit
        end         = start + limit - 1
        articleIds  = redis.zrange(order, start, end, desc = True)
        articleList = {};

        for id in articleIds:
                articleData       = redis.hgetall(id)
                articleData['id'] = id
                articleList[id]   = articleData
  
        return articleList

#设置,移除文章分组
def add_remove_group(article, add = [], remove = [], redis = redis):
        for group in add:
                groupKey = 'group:' + group
                redis.sadd(groupKey, article)
        for group in remove:
                redis.srem(groupKey, article)

#按评分或时间排名取出分组下的文章
def get_group_articles(group, order, page = 25, limit = 25, redis = redis):
        key = order + group

        if (not redis.exists(key)):
                redis.zinterstore(key,
                ['group:' + group, order],
                aggregate = 'max'
                )
                redis.expire(key, 5)

        return get_articles(key, page, limit)

  

3.发布文章

  调用

article   = post(articleData)
articleId = article.partition(':')[-1]

add_remove_group(article, add = ['redis'])

#获取文章
print('----------------------------------Article ID------------------------------')
print(articleId)

#获取文章
print('----------------------------------Article------------------------------')
print(redis.hgetall(article))

#获取文章发布时间
print('----------------------------------Voted Users------------------------------')
print(redis.smembers('voted:' + articleId))

#获取所有文章评分,并且按照分数排名
print('----------------------------------Rank------------------------------')
print(redis.zrange('score', 0, -1, desc=True, withscores=True))

#获取所有文章发布时间
print('----------------------------------Post Time------------------------------')
print(redis.zrange('time', 0, -1, desc=True, withscores=True))

  

  输出结果

 

88
----------------------------------Article------------------------------
{b'poster': b'user:001', b'title': b'Ptython', b'content': b'hello world', b'votes': b'1', b'time': b'1596951581.718217'}
----------------------------------Voted Users------------------------------
{b'user:001'}
----------------------------------Rank------------------------------
[(b'article:87', 1596951443.171613), (b'article:86', 1596951389.8698218), (b'article:85', 1596951275.8035266), (b'article:84', 1596951174.1960804), (b'article:83', 1596951071.6917884), (b'article:10', 1596816080.909939), (b'article:9', 1596816058.8451862), (b'article:8', 1596816047.3071418), (b'article:7', 1596816011.8706625), (b'article:6', 1596815930.085024), (b'article:5', 1596815917.6721313), (b'article:4', 1596815862.928912), (b'article:3', 1596815838.7520182), (b'article:2', 1596814204.1336813), (b'article:1', 1596813938.6256502), (b'article:88', 240.0)]
----------------------------------Post Time------------------------------
[(b'article:88', 1596951581.718217), (b'article:87', 1596951203.171613), (b'article:86', 1596951149.8698218), (b'article:85', 1596951035.8035266), (b'article:84', 1596950934.1960804), (b'article:83', 1596950831.6917884), (b'article:82', 1596950758.6923993), (b'article:81', 1596950643.6892672), (b'article:80', 1596950633.143089), (b'article:10', 1596815840.909939), (b'article:9', 1596815818.8451862), (b'article:8', 1596815807.3071418), (b'article:7', 1596815771.8706625), (b'article:6', 1596815690.085024), (b'article:5', 1596815677.6721313), (b'article:4', 1596815622.928912), (b'article:3', 1596815598.7520182), (b'article:2', 1596813964.1336813), (b'article:1', 1596813698.6256502)]

 

  

 

posted @ 2020-08-07 23:29  coder_xds  阅读(759)  评论(0编辑  收藏  举报