Original design
This is how I originally installed my Models :
class UserData(db.Model): user = db.UserProperty() favorites = db.ListProperty(db.Key)
On each page on which the story was shown, I would query UserData for the current user:
user_data = UserData.all().filter('user =' users.get_current_user()).get() story_is_favorited = (story in user_data.favorites)
New design
After watching this talk: Google I / O 2009 - Scalable complex applications in App Engine , I wondered if I could configure it more efficiently.
class FavoriteIndex(db.Model): favorited_by = db.StringListProperty()
Story Model the same, but I got rid of the UserData Model . Each instance of the new FavoriteIndex Model has a Story instance as a parent. And each FavoriteIndex stores a list of user IDs in it favorited_by .
If I want to find all stories that have been approved by a specific user:
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)
This approach avoids serialization / deserialization that are otherwise associated with ListProperty.
Efficiency vs Simplicity
I'm not sure how effective the new design is, especially after the user solves the favorite 300 stories, but here's why I like it:
The selected story is related to the user, not user data
On the page where I show Story , it's pretty easy to ask Story if he was selected (without calling a separate object filled with user data).
fav_index = FavoriteIndex.all().ancestor(story).get() fav_of_current_user = users.get_current_user().user_id() in fav_index.favorited_by
It is also easy to get a list of all the users who prefer the story (using the method in # 2)
Is there an easier way?
Please, help. How is this usually done?
wings source share