예제 #1
0
def create_connections(N, M, K1=None, K2=None):
    """Create connections from users 1 - N.

    Users with uid less equal than M will be considered as celebrities
    having many followers.
    
    Parameters
    ----------
    N: int
        The number of users.
    M: int
        The number of celebrities.
    K1: int
        The average number of followers for celebrities. Default: 0.05 * N.
    K2: int
        The average number of followers for normal users. Default: 0.001 * N.
    """
    assert N >= M
    if K1 is None:
        K1 = int(N * 0.05)
    if K2 is None:
        K2 = int(N * 0.001)
    for uid in range(1, M + 1):
        pipe = conn.pipeline(False)
        s = random.randint(1, N - K1)
        for follower_uid in range(s, s + K1):
            follow(follower_uid, uid, pipe)
        pipe.execute()
    for uid in range(M + 1, N + 1):
        pipe = conn.pipeline(False)
        s = random.randint(1, N - K2)
        for follower_uid in range(s, s + K2):
            follow(follower_uid, uid, pipe)
        pipe.execute()
예제 #2
0
def unfollow(follower, followee):
    """Remove a connection between follower and followee."""
    follow_ts = conn.zscore(utils.get_followers_key(followee), follower)
    _tweets = tweets.get_tweets_since(followee, follow_ts, {'tid', 'uid'})
    pipe = conn.pipeline()
    pipe.zrem(utils.get_followers_key(followee), follower)
    pipe.zrem(utils.get_followees_key(follower), followee)
    tweets.delete_tweets(_tweets, pipe)
    pipe.execute()
예제 #3
0
def get_tweets(tids, fields=None):
    """Return tweets with specified tids."""
    pipe = conn.pipeline(False)
    for tid in tids:
        if fields is None:
            pipe.hgetall(utils.get_tweet_key(tid))
        else:
            pipe.hmget(utils.get_tweet_key(tid), *fields)
    tweets = [Tweet.load_dict(d) for d in pipe.execute()]
    return tweets
예제 #4
0
def create_tweets(N, M, K1=200, K2=80):
    """Create tweets from users 1 - N.

    Users with uid less equal than M will be considered as celebrities
    having many followers.
    """
    assert N >= M
    pipe = conn.pipeline(False)
    for uid in range(1, M + 1):
        pipe = conn.pipeline(False)
        for _ in range(K1):
            post_tweet(uid, pipe, body=fake_tweet_body(),
                       location=fake_location())
        pipe.execute()
    for uid in range(M + 1, N + 1):
        pipe = conn.pipeline(False)
        for _ in range(K2):
            post_tweet(uid, pipe, body=fake_tweet_body(),
                       location=fake_location())
        pipe.execute()
예제 #5
0
def delete_tweets(tweets, pipe=None):
    """Delete tweets with specified tids."""
    execute = True
    if pipe is None:
        pipe = conn.pipeline(False)
        execute = True
    else:
        execute = False
    for tweet in tweets:
        delete_tweet(tweet, pipe)
    if execute:
        pipe.execute()
예제 #6
0
def follow(follower, followee, pipe=None):
    """Create a connection between follower and followee."""
    if pipe is None:
        pipe = conn.pipeline()
        execute = True
    else:
        execute = False
    pipe.zadd(utils.get_followers_key(followee),
              follower, utils.get_timestamp())
    pipe.zadd(utils.get_followees_key(follower),
              followee, utils.get_timestamp())
    if execute:
        pipe.execute()
예제 #7
0
def delete_tweet(tweet, pipe=None):
    """Delete a tweet."""
    followers = users.get_followers(tweet.uid)
    if pipe is None:
        pipe = conn.pipeline(False)
        execute = True
    else:
        execute = False
    pipe.zrem(utils.get_user_tweets_key(tweet.uid), tweet.tid)
    pipe.zrem(utils.get_timeline_key(tweet.uid), tweet.tid)
    for follower_uid in followers:
        pipe.zrem(utils.get_timeline_key(follower_uid), tweet.tid)
    pipe.delete(utils.get_tweet_key(tweet.tid))
    if execute:
        pipe.execute()
예제 #8
0
def refresh_timeline(uid):
    """Refresh user's timeline.

    Fetch all delayed tweets from his/her followees.
    """
    last_tid = conn.zrevrange(utils.get_timeline_key(uid), 0, 0)
    last_tweet = tweets.get_tweet(last_tid)
    if not last_tweet:
        return
    followees = get_followees(uid)
    pipe = conn.pipeline(False)
    for followee in followees:
        _tweets = tweets.get_tweets_since(followee, last_tweet.ts,
                                          {'tid', 'datetime'})
        for tweet in _tweets:
            pipe.zadd(utils.get_timeline_key(uid), tweet.tid, tweet.ts)
    pipe.execute()
예제 #9
0
def post_tweet(uid, pipe=None, **tweet_info):
    """Create a new tweet with basic infomation.

    Parameters
    ----------
    uid: str
        User ID.
    pipe: Pipeline object
        A Redis pipeline object, if given, need to execute manually outside
        this function.
    body: str
        The body of the tweet.
    location: str
        The location when posting this tweet.
    original: bool
        Whether this tweet is an original tweet or just a retweet.
    """
    tweet_info['uid'] = uid
    tweet_info['tid'] = uuid4().hex
    tweet_info['datetime'] = datetime.now()
    tweet_info.setdefault('original', True)
    tweet = Tweet.load_dict(tweet_info)
    if pipe is None:
        pipe = conn.pipeline(False)
        execute = True
    else:
        execute = False
    pipe.hmset(utils.get_tweet_key(tweet.tid), tweet.dump_dict())
    pipe.zadd(utils.get_user_tweets_key(uid), tweet.tid, tweet.ts)
    pipe.zadd(utils.get_timeline_key(uid), tweet.tid, tweet.ts)
    if users.get_followers_count(uid) < config.DIRECT_INSERT_THRES:
        # Perform direct insertion
        followers = users.get_followers(uid)
        for follower_uid in followers:
            pipe.zadd(utils.get_timeline_key(follower_uid), tweet.tid,
                      tweet.ts)
    if execute:
        pipe.execute()