在 AppEngine 上关注数据存储区模型结构 - 按日期对关注者排序
在我的应用程序中,用户可以关注其他用户,并在他们关注的人执行活动时获取更新。
我以这种方式存储关注关系:
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)
获取关注者以及用户关注的用户(关注者和关注者):
'''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)
因此,我想按关注日期对 my_user 关注者进行排序(我在上述模型中没有跟踪),但是我不确定最好的方法是什么。以下是我能想到的选项:
1)使用“桥接”模型代替当前的联系人结构(db.Model):
class Contacts(db.Model):
follower = db.ReferenceProperty(User)
following = db.ReferenceProperty(User)
date_created = db.DateTimeProperty(auto_now_add=True)
但是,我仍然需要弄清楚如何确保我有唯一的关注者-> ;以下实体:follower=user1、following=user2 不应重复。我认为,如果我对查询应用 2 个过滤器,我就可以做到这一点。
2)保留当前的模型结构,但不是在 Contacts(db.Model) 中包含键列表,而是存储一个元组:[user_key, date_created],如下所示:
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)
但是,这样我就必须处理联系人列表: - 我必须从 StringList() 中的每个字符串中提取用户键和 date_created - 然后我可以按创建日期对用户密钥列表进行排序
3)最后一个解决方案(显然效率不高):保留原始数据库结构,并将用户关注活动存储在单独的模型中 - 每个关注操作都使用 date_created 字段单独存储。使用此表仅能够按日期对用户关注者列表进行排序。这当然意味着我将执行两个数据存储放置 - 一个放置到 Contacts(),另一个放置到 FollowNewsFeed(),如下所示:
Class FollowNewsFeed(db.Model):
''' parent = a User follower'''
following = db.ReferenceProperty(User)
date_created = db.DateTimeProperty(auto_add_now=True)
非常感谢有关处理此问题的最佳方法的任何见解:)
谢谢!
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 appreciated :)
Thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我会使用一个模型来从用户映射到他们的目标,而不是一个列表:
插入一个新实例或删除一个现有实例可能比修改一个巨大的列表并重新保存它更快。此外,随着关注的大小增长,您可以查询列表的子集,而不是获取全部列表(请参阅下文了解原因)。
您可以获得额外的属性空间,而不必担心需要重新设计和修改列表。
不必担心列表的索引限制(每个项目占用一个槽,最多 5000)。
不幸的是,您可能会更快地达到另一个限制:
这意味着每个元素将消耗一个槽[例如。
在 (1,2,3)
= 3 个槽]。因此,即使数量相对较小(约 30 个关注者),您也需要多次访问数据库并附加结果。假设人们不想在他们的页面上花费数百年的时间来加载和计时,那么您将需要对他们可以关注的人数进行某种类型的限制。如果有 100 人被关注,您将需要 4-5 次行程,并且必须在应用程序内或通过 JavaScript 在客户端对数据进行排序。
I would use a model to map from the user to their target rather then a list:
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).
You get extra attribute space and don't have to worry as much about needing to redesign and fudge with lists down the road.
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:
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.