如何在appengine中建模追随者流?

时间:2010-05-24 15:59:38

标签: python database-design google-app-engine bigtable

我正在尝试设计表来建立跟随者关系。

假设我有一个包含用户,主题标签和其他文本的140char记录流。

用户关注其他用户,也可以关注主题标签。

我概述了我在下面设计的方式,但我的设计有两个限制。我想知道其他人是否有更聪明的方法来实现同样的目标。

这个问题是

  1. 将为每条记录复制关注者列表
  2. 如果添加新关注者或删除一个关注者,则“全部” 记录必须更新。
  3. 代码

    class HashtagFollowers(db.Model):
        """
        This table contains the followers for each hashtag
        """
        hashtag = db.StringProperty()
        followers = db.StringListProperty()
    
    class UserFollowers(db.Model):
        """
        This table contains the followers for each user
        """
        username = db.StringProperty()
        followers = db.StringListProperty()
    
    class stream(db.Model):
        """
        This table contains the data stream
        """
        username = db.StringProperty()
        hashtag = db.StringProperty()
        text = db.TextProperty()
    
        def save(self):
            """
            On each save all the followers for each hashtag and user
            are added into a another table with this record as the parent
            """
            super(stream, self).save()
            hfs = HashtagFollowers.all().filter("hashtag =", self.hashtag).fetch(10)
            for hf in hfs:
                sh = streamHashtags(parent=self, followers=hf.followers)
                sh.save()
            ufs = UserFollowers.all().filter("username =", self.username).fetch(10)
            for uf in ufs:
                uh = streamUsers(parent=self, followers=uf.followers)
                uh.save()
    
    
    
    class streamHashtags(db.Model):
        """
        The stream record is the parent of this record
        """
        followers = db.StringListProperty() 
    
    class streamUsers(db.Model):
        """
        The stream record is the parent of this record
        """
        followers = db.StringListProperty()
    
    Now, to get the stream of followed hastags 
    
        indexes = db.GqlQuery("""SELECT __key__ from streamHashtags where followers = 'myusername'""")
        keys = [k,parent() for k in indexes[offset:numresults]]
        return db.get(keys)
    

    有更聪明的方法吗?

4 个答案:

答案 0 :(得分:5)

您要解决的问题称为扇出问题。

来自Google App Engine团队的Brett Slatkin就App Engine上的扇出问题提供了一个高效/可扩展的解决方案。你可以在这里找到一个关于这个话题的视频:

http://code.google.com/events/io/2009/sessions/BuildingScalableComplexApps.html

答案 1 :(得分:1)

是的,这是其他人注意到的扇出问题,感兴趣的人应该看看Brett Slatkin的讲话。

但是,我提出了两个具体限制,即

  • 将为每条记录复制关注者列表

他们说这不是一个错误,而是一个功能。事实上,正是通过这种方式,在发动机上进行了扇形调节。

  • 如果添加了新关注者或删除了一个关注者,则必须更新“所有”记录。

或者什么也不做,以便不遵循未来的记录。换句话说,人们不仅仅关注人们的流,而是在特定时间跟随人们的流。因此,如果在第2天您取消关注,您的关注者流仍将显示来自第一天进入的用户的记录,但不会显示第二天及以后的记录。 [注意:这与推特的方式不同]

答案 2 :(得分:0)

您可以使用reference属性,然后在其中包含一个包含关注者的公用表,您可以参考

答案 3 :(得分:-1)

我不确定如何在Google App-Engine中执行此操作,但我会考虑使用一个数据库架构:

Tables:
    User    -- a table of users with their attributes
    HashTag -- a table of HashTags with their attributes
    Follows -- a table that defines who follows whom

Columns in the Follows table:
    followed int,         -- the id of the followed entity (could be 
                             User or Hashtag)
    followed_is_user bit, -- whether the followed item is a User
    followed_is_tag bit,  -- whether the followed item is a HashTag
    follower int          -- the id of the follower (this can only be 
                             a User so you may want to make this a foreign 
                             key on the User table)

您可以将两位列压缩为一列,但这样可以添加用户将来可以使用的其他内容。