一个好的数据模型用于查找用户的喜欢故事
最初的设计
我最开始是这样设置我的 Models
的:
class UserData(db.Model):
user = db.UserProperty()
favorites = db.ListProperty(db.Key) # list of story keys
# ...
class Story(db.Model):
title = db.StringProperty()
# ...
在每个显示故事的页面上,我会查询当前用户的用户数据:
user_data = UserData.all().filter('user =' users.get_current_user()).get()
story_is_favorited = (story in user_data.favorites)
新的设计
在看了这个讲座之后: Google I/O 2009 - 可扩展的复杂应用程序在 App Engine 上,我想知道是否可以更高效地设置这些东西。
class FavoriteIndex(db.Model):
favorited_by = db.StringListProperty()
Story Model
还是一样,但我去掉了 UserData Model
。新的 FavoriteIndex Model
的每个实例都有一个 Story
实例作为父级。而每个 FavoriteIndex
都在它的 favorited_by
属性中存储了一份用户 ID 的列表。
如果我想找到某个用户收藏的所有故事:
index_keys = FavoriteIndex.all(keys_only=True).filter('favorited_by =', users.get_current_user().user_id())
story_keys = [k.parent() for k in index_keys]
stories = db.get(story_keys)
这种方法避免了与 ListProperty 相关的序列化和反序列化问题。
效率与简单性
我不确定新的设计有多高效,特别是在用户决定收藏 300 个故事之后,但我喜欢它的原因有:
被收藏的故事是和用户关联的,而不是和她的
user data
关联。在我显示
story
的页面上,询问这个story
是否被收藏是相当简单的(不需要调取一个单独的包含用户数据的实体)。fav_index = FavoriteIndex.all().ancestor(story).get() fav_of_current_user = users.get_current_user().user_id() in fav_index.favorited_by
获取所有收藏了某个故事的用户列表也很简单(使用第 2 点的方法)。
有没有更简单的方法?
请帮帮我。这种事情通常是怎么做的?
4 个回答
你可以把收藏索引想象成在两个模型之间的连接
class FavoriteIndex(db.Model):
user = db.UserProperty()
story = db.ReferenceProperty()
或者
class FavoriteIndex(db.Model):
user = db.UserProperty()
story = db.StringListProperty()
这样的话,当你根据用户查询时,会返回每个用户收藏的故事对应的一个 FavoriteIndex 对象
你也可以根据故事来查询,看看有多少用户收藏了它。
你不想随便去查找任何东西,除非你知道它的数量很少。
我不打算直接回答你的问题,但我可以给你一个很小的建议:你可以把这段代码:
if story in user_data.favorites:
story_is_favorited = True
else:
story_is_favorited = False
换成这一行:
story_is_favorited = (story in user_data.favorites)
如果你不想的话,其实也可以不把story in user_data.favorites
放在括号里;我只是觉得这样看起来更清晰。
你所描述的方案很好。不过,你还可以进一步优化:对于每个收藏的故事,创建一个叫做'UserFavorite'的实体,把它作为相关故事条目的子实体(或者说,作为UserInfo条目的子实体),并把这个实体的名字设置为用户的唯一ID。这样一来,你就可以通过简单的获取操作来判断用户是否收藏了某个故事:
UserFavorite.get_by_name(user_id, parent=a_story)
获取操作的速度比查询快3到5倍,所以这是一个很大的提升。