需要AppEngine数据存储区设计建议

时间:2011-09-29 10:15:15

标签: java google-app-engine

我正在建立一个分布式会计系统。 就数据库结构和要求而言,最简单的方法是将应用程序描述为类似Twitter的应用程序,但具有14个表的分层数据库结构。 使用该应用程序的公司可能拥有1个或更多用户,所有用户都共享公司信息。

目前,每个实体代表一种记录类型,即客户,发票等。 所有实体都有一个父级,即应用程序的用户。 (出于HRD查询一致性原因)

对数据库的每个查询都包含14个AppEngine查询。每张桌子一个。 该查询涉及属性过滤。

新要求是用户的查询可能需要基于每个其他用户的不同属性值。 这意味着我们需要(公司用户数量的14倍)AppEngine查询。这似乎太过分了。

可以按属性过滤的无状态祖先查询真的很好,唉,不能做:)

我的选择是:

  1. 将实体类型设置为User。没有父母。这意味着所有记录类型都是混合的。 (过滤的字段存在于所有记录类型中)。 这不漂亮。但你会考虑吗?

  2. 只有过滤器才有固定的实体种类和查询。结果相当于Kindless Ancestor查询。但是,我担心多用户使用它会很慢。

  3. 有些数字: 我们计划10,000家公司,每家公司平均5个用户,每个记录类型有1到500万条记录。 (总共x 14)

    感谢您耐心等等。::)

1 个答案:

答案 0 :(得分:1)

老实说,我发现遵循你的描述很有挑战性,所以这可能不合时宜。查看现有代码可能会有所帮助。但我知道你想要一个有效的无产阶级祖先查询的替代品,所以让我们从那里开始。

考虑对数据模型进行反规范化以包含仅用于查询的元实体:

class User(db.Model):
  pass

class OwnedObject(db.Expando):
  object_key = db.StringProperty()

class Customer(db.Model):
  name = db.StringProperty()
  created_on = db.DateProperty()

class Invoice(db.Model):
  amount = db.IntegerProperty()
  created_on = db.DateProperty()

# on write
customer = Customer()
customer.name = name
customer.created_on = date.today()
customer.put()

user = User(key_name=users.get_current_user().user_id())

owned_object = OwnedObject(parent=user)
owned_object.object_key = customer.key()
owned_object.created_on = customer.created_on
owned_object.put()

# on read
query = OwnedObject.all()
query.ancestor(user)
query.filter('created_on =', date.today())

entities = db.get([x.object_key for x in query])

所以,你在写作方面做的更多,而不是阅读。

每个真实实体都与OwnedObject实体耦合,该实体从适当的祖先下降并指向真实实体的密钥。 OwnedObject是一个expando,因此您将急切地指定要查询的任何属性(在此示例中为created_on)。

在读取时,您可以查询已复制到expando元实体的任何属性,并且可以使用一个查询和一个批量获取的固定开销来撤回所有用户的对象。

修改:您可以使用PolyModel在没有元实体的情况下完成类似的事情。