0

I am using appengine with python 2.7 and webapp2 framework. I am not using ndb.model.

I have the following model:

class Story(db.Model);
    name = db.StringProperty()

class UserProfile(db.Model):
    name = db.StringProperty()
    user = db.UserProperty()

class Tracking(db.Model):
   user_profile = db.ReferenceProperty(UserProfile)
   story = db.ReferenceProperty(Story)
   upvoted = db.BooleanProperty()
   flagged = db.BoolenProperty()

A user can upvote and/or flag a story but only once. Hence I came up with the above model. Now when a user clicks on the upvote link, on the database I try to see if the user has not already voted it, hence I do try to do the following:

  1. get the user instance with his id as up = db.get(db.Key.from_path('UserProfile', uid))

  2. then get the story instance as follows s_ins = db.get(db.Key.from_path('Story', uid))

  3. Now it is the turn to check if a Tracking based on these two exist, if yes then don't allow voting, else allow him to vote and update the Tracking instance.

What is the most convenient way to fetch a Tracking instance given an id(db.key().id()) of user_profile and story?

What is the most convenient way to save a Tracking model having given a user profile id and an story id?

Is there a better way to implement tracking?

4

2 回答 2

1

您可以尝试使用键列表进行跟踪,而不是使用单独的跟踪/用户/故事条目:

class Story(db.Model);
  name = db.StringProperty()

class UserProfile(db.Model):
  name = db.StringProperty()
  user = db.UserProperty()

class Tracking(db.Model):
  story = db.ReferenceProperty(Story)
  upvoted = db.ListProperty(db.Key)
  flagged = db.ListProperty(db.Key)

因此,当您想查看用户是否为给定故事投票时:

Tracking.all().filter('story =', db.Key.from_path('Story', uid)).filter('upvoted =', db.Key.from_path('UserProfile', uid)).get(keys_only=True)

现在这里唯一的问题是投票/标记列表的大小不能变得太大(我认为限制是 5000),所以你必须创建一个类来管理这个(也就是说,当添加到 upvoted /标记列表,检测是否存在 X 条目,如果存在,则启动新的跟踪对象以保存附加值)。您还必须进行事务处理,并且对于 HR,您有每秒 1 次写入的阈值。这可能是也可能不是问题,具体取决于您的预期用例。绕过写入阈值的一种方法是使用拉取队列实现支持/标记,并有一个 cron 作业根据需要拉取和批量更新跟踪对象。

这种方法有其优点/缺点。最明显的缺点是我刚刚列出的那些。然而,优点可能是值得的。您可以从单个列表(或多个,具体取决于故事的受欢迎程度)中获取对故事进行投票/标记的用户的完整列表。您可以获得完整的用户列表,而对数据存储的查询要少得多。此方法还应占用更少的存储空间、索引空间和元数据空间。此外,将用户添加到跟踪对象会更便宜,而不是为每个属性编写一个新对象 + 2 次写入,您只需为该对象支付 1 次写入 + 为列表条目添加 2 次写入(9 次写入 vs 3 次写入用于将用户添加到预先存在的跟踪故事,或 9 vs 7 用于未跟踪的故事)

于 2012-09-27T18:20:47.827 回答
0

你的提议听起来很合理。

不要使用应用引擎生成的密钥进行跟踪。因为故事/用户的组合应该是唯一的,所以创建您自己的密钥作为故事/用户的组合。就像是

tracking = Tracking.get_or_insert(str(story.id) + "-" + str(user.id), **params)

如果您知道故事/用户,那么您始终可以通过键名获取跟踪。

于 2012-09-27T02:08:40.883 回答