开发者

Follow datastore model structure on AppEngine - Order followers by date

In my app, users can follow other users, and get updates whenever the people they follow perform an activity.

I store the follow relationships in this manner:

class User(db.Model):
  ''' User details '''
  username = db.StringProperty()

class Contacts(db.Model):
    '''Store users contacts
       parent= User (follower)
       key_name= Users username (follower)
       contacts = A list of keys of Users that a User follows '''
    contacts = db.ListProperty(db.Key)
    last_updated = db.DateTimeProperty(auto_now=True)

Getting followers, and Users that a user follows (followers & following):

'''Get Users that my_user follows'''
my_user = User().all().fetch(1)
contacts = Contacts.get_by_key_name(my_user.username).contacts

''' get my_user followers - copied from an answer here on stackoverflow '''
follower_index = models.Contacts.all(keys_only=True).filter('contacts =',my_user)
follower_keys = [f.parent() for f in follower_index]
followers = db.get(follower_keys)

So, I want to order my_user followers by follow date (which I don't track in the above models), but I'm not sure what is the best way to do that. Here are the options I can think of:

1) Instead of the current structure for Contacts(db.Model), use a "bridge" model:

class Contacts(db.Model):
  follower = db.ReferenceProperty(User)
  following = db.ReferenceProperty(User)
  date_created = db.DateTimeProperty(auto_now_add=True)

However, I still have to figure out how to make sure that I have unique follower->following entities: follower=user1, following=user2 should not repeat. I can do that if I apply 2 filters to my query I think.

2) Keep the current model structure, but instead of having a list of keys in Contacts(db.Model), store a tuple: [user_key, date_created] as follows:

class Contacts(db.Model):
        '''Store users contacts
           parent= User (follower)
           key_name= Users username (follower)
           contacts = A list of Tuples: User.key(), date_created '''
        contacts = db.StringListProperty()
        last_updated = db.DateTimeProperty(auto_now=True)

However, this way i'll have to process the list of contacts: - I have to extract the User keys and date_created from each string in the StringList() - Then I can order the list of User keys by date created

3) Last solution (clearly not efficient): keep the original db structure, and store user follow activity in a separate Model - each follow action is stored separately with a date_created field. Use this table only to be able to order the list of user followers by date. This of course means that I'll do two datastore puts - one to Contacts() and another to FollowNewsFeed() as follows:

Class FollowNewsFeed(db.Model):
  ''' parent = a User follower'''
  following = db.ReferenceProperty(User)
  date_created = db.DateTimeProperty(auto_add_now=True)

Any insights on the best way to deal with this are highly开发者_如何学C appreciated :)

Thank you!


I would use a model to map from the user to their target rather then a list:

  1. Inserting a new instance or deleting an existing one will probably be faster than modifying a huge list and resaving it. Also as the size of followed grows you can query a subset of the list rather that fetching it all (see below for why).

  2. You get extra attribute space and don't have to worry as much about needing to redesign and fudge with lists down the road.

  3. Don't have to worry about index limits with lists (each item takes up a slot, up to 5000).

Unfortunately you will probably hit another limit much sooner:

A single query containing != or IN operators is limited to 30 sub-queries.

Which means each element will consume a slot [ex. in (1,2,3) = 3 slots]. So even at a relatively small amount (~30 followers) you will need to make multiple trips to the database and append results.

Assuming people don't want to go insane at their page taking hundreds of years to load and timing you will need some type of limit on how many people they can follow. At 100 people being followed you would need a good 4-5 trips and have to sort the data within your app or on the client side via javascript.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜