以下是我最初设置Models
的方式:
class UserData(db.Model):
user = db.UserProperty()
favorites = db.ListProperty(db.Key) # list of story keys
# ...
class Story(db.Model):
title = db.StringProperty()
# ...
在显示故事的每个页面上,我都会向UserData查询当前用户:
user_data = UserData.all().filter('user =' users.get_current_user()).get()
story_is_favorited = (story in user_data.favorites)
在看了这个演讲之后:Google I/O 2009 - Scalable, Complex Apps on 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中的方法)
请帮忙。这种事情通常是怎么做的?
答案 0 :(得分:2)
您所描述的是一个很好的解决方案。但是,您可以进一步优化它:对于每个收藏夹,创建一个“UserFavorite”实体作为相关Story条目的子实体(或者等效地,作为UserInfo条目的子实体),将键名设置为用户的唯一ID。通过这种方式,您可以确定用户是否使用简单的get:
收藏了故事UserFavorite.get_by_name(user_id, parent=a_story)
获取操作比查询快3到5倍,因此这是一项重大改进。
答案 1 :(得分:1)
我不想解决您的实际问题,但这里有一个非常小的提示:您可以替换此代码:
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
附近;我认为这更具可读性。
答案 2 :(得分:1)
您可以将喜欢的索引设为两个模型上的连接
class FavoriteIndex(db.Model):
user = db.UserProperty()
story = db.ReferenceProperty()
或
class FavoriteIndex(db.Model):
user = db.UserProperty()
story = db.StringListProperty()
然后,您的用户查询会为用户收藏的每个故事返回一个FavoriteIndex对象
您还可以按故事查询,以查看有多少用户已将其收藏。
您不希望扫描任何内容,除非您知道它仅限于小尺寸
答案 3 :(得分:1)
使用您的新设计,您可以查询用户是否通过查询收藏了某个故事 您不需要UserFavorite类实体 它是一个keys_only查询,因此不如get(key)快,但比普通查询快 FavoriteIndex类都具有相同的key_name ='favs' 您可以根据__key__进行过滤。
a_story = ......
a_user_id = users.get_current_user().user_id()
favIndexKey = db.Key.from_path('Story', a_story.key.id_or_name(), 'FavoriteIndex', 'favs')
doesFavStory = FavoriteIndex.all(keys_only=True).filter('__key__ =', favIndexKey).filter('favorited_by =', a_user_id).get()
如果您使用多个FavoriteIndex作为故事的子节点,则可以使用祖先过滤器
doesFavStory = FavoriteIndex.all(keys_only=True).ancestor(a_story).filter('favorited_by =', a_user_id).get()