我在python 2.7和webapp2框架中使用appengine。我使用ndb.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()
用户可以上传和/或标记故事,但只能进行一次。因此我提出了上述模型。
现在,当用户点击upvote
链接时,我会尝试查看用户是否尚未投票,因此我尝试执行以下操作:
获取身份为up = db.get(db.Key.from_path('UserProfile', uid))
然后按如下方式获取故事实例s_ins = db.get(db.Key.from_path('Story', uid))
现在轮到检查基于这两者的Tracking
是否存在,如果是则不允许投票,否则允许他投票并更新跟踪实例。
在Tracking
和db.key().id()
的ID(user_profile
)获取 story
实例时,最方便的方法是什么?
保存给定用户个人资料ID和故事ID的Tracking
模型最方便的方法是什么?
是否有更好的方法来实施跟踪?
答案 0 :(得分: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)
现在唯一的问题是upvoted / flagged列表的大小不能太大(我认为限制是5000),所以你必须创建一个类来管理它(也就是说,添加时)对于upvoted / flagged列表,检测是否存在X条目,如果存在,则启动一个新的跟踪对象以保存其他值)。您还必须进行此事务处理,并且使用HR时,您的每秒写入阈值为1。根据您的预期用例,这可能是也可能不是问题。围绕写入阈值的方法是使用pull-queues实现upvotes / flags,并根据需要提供一个cron作业来拉取和批量更新跟踪对象。
这种方法有其优点/缺点。最明显的缺点是我刚刚列出的那些。然而,专业人士可能是值得的。您可以从单个列表中获取完整/标记故事的用户的完整列表(或多个,具体取决于故事的受欢迎程度)。您可以获得对数据存储区的查询少得多的用户的完整列表。此方法还应占用较少的存储空间,索引和元数据空间。此外,将用户添加到跟踪对象将更便宜,而不是为每个属性写入一个新对象+2次写入,您只需为对象写入1次写入,为列表中的条目写入2次写入(9次对3次写入)用于将用户添加到预先存在的跟踪故事中,或者为未跟踪的故事添加9对7)
答案 1 :(得分:0)
你的建议听起来很合理。
请勿使用应用引擎生成的密钥进行跟踪。因为故事/用户的组合应该是唯一的,所以创建自己的密钥作为故事/用户的组合。像
这样的东西tracking = Tracking.get_or_insert(str(story.id) + "-" + str(user.id), **params)
如果你知道故事/用户,那么你总是可以按密钥名称来获取跟踪。