在GAE / P中创建自己的活动记录

时间:2018-03-29 12:24:05

标签: python google-app-engine

我想在我的应用中记录用户活动,以便向用户展示,也可以用于管理目的。我的客户是公司,所以我可以在三个级别上展示活动:

  1. 单个用户的活动
  2. 公司所有用户的活动
  3. 所有活动
  4. 要进行日志记录,我会创建一个模型来存储日志条目。我看到了一些这样做的方法。

    首先,我可以将每个记录的活动存储在自己的实体中,然后根据需要进行查询:

    class Activity(ndb.Model):
        activity = ndb.StringProperty()
        user_id = ndb.StringProperty()
        company_id = ndb.StringProperty()
    

    其次,我可以将用户的所有活动存储在一个实体中:

    class UserActivity(ndb.Model):
        activity = ndb.StringProperty(repeated=True) # Note this is now a list
        company_id = ndb.StringProperty()
    

    第三,我可以将公司的所有活动存储在一个实体中:

    class CompanyActivity(ndb.Model):
        activity = ndb.StringProperty(repeated=True) # Would store user_id here somehow
    

    这三个选项的功能/性能权衡是什么?我知道如果频繁出现交易,第二和第三选项存在潜在的争用问题,但是为了讨论,我们假设这不是问题。

    对于第二个和第三个选项,减少数据存储区实体的总数是否有任何显着优势(因为它们将合并为更少的实体)?或者我应该选择第一个选项?

2 个答案:

答案 0 :(得分:3)

使用重复属性的唯一好处是,您可以避免最终的一致性问题:每当您阅读UserActivityCompanyActivity实体时,您都会知道自己获得了所有活动的完整列表。使用第一种方法时,您必须进行查询以获取此类列表,并且列表可能会错过最近的活动,因为相应的查询索引可能尚未更新以反映它们。

但是,除了您提到的潜在争用问题之外,重复属性方法还有另一个缺点:随着越来越多的活动被添加到列表中,这些实体的大小将逐渐增加,这意味着成:

  • 逐渐减慢get() / put()次,因此整体应用性能逐渐恶化
  • 达到最大数据存储区实体大小的风险(约1MB,请参阅Limits),这需要额外的逻辑来跨多个实体拆分列表

特别是第3种方法还需要一种不那么简单的方法来获取每用户活动报告。

我坚持第一种方法,它是最灵活和可扩展的方法,缺点很小:

  • 最终的一致性问题是恕我直言,不是一个显示阻止(并且可能有减少其影响的方法)
  • 额外的存储空间(对于存储在每个Activity实体中的用户/公司ID属性加上较大的索引,因为实体数量较多)是恕我直言,值得(存储便宜)。

答案 1 :(得分:0)

我还建议第一种方法,但使用KeyProperty

class Activity(ndb.Model):
    activity = ndb.StringProperty()
    user_id = ndb.KeyProperty(kind='User')
    company_id = ndb.KeyProperty(kind='Company')

代码从一开始就会更加清晰,您可以随时进行微调。

对于其他人来说,Dan已经非常清楚地涵盖了最重要的一点。