在Google App Engine(GAE)数据存储区中复制键名和父级作为属性?

klk*_*lkh 2 python google-app-engine google-cloud-datastore

在阅读了GAE数据存储API之后,我仍然不确定是否需要将键名和父项复制为实体的属性.

假设有两种实体:Employee和Division.每个员工都有一个部门作为其父级,并由帐户名称标识.我使用帐户名作为员工的密钥名称.但是在为Employee建模时,我仍然将这两个作为属性:

division = db.ReferenceProperty(Division)
account_name = db.StringProperty()
Run Code Online (Sandbox Code Playgroud)

显然,我必须手动保持division与其父级一致,并account_name使用其密钥名称.我正在做这项额外工作的原因是:

  1. 我担心GQL/Datastore API可能不支持父级和密钥名称以及普通属性.有什么我可以做的关于一个属性但不是父或关键名称(或他们基本上是引用属性)?如何在GQL查询中使用键名?
  2. 关键名称和父母的含义不是特别清楚.由于名称不是自我描述的,我必须通知其他贡献者我们使用帐户名作为关键名称...

但这实际上是不必要的工作,浪费时间和存储空间.我无法摆脱SQL思维 - 为什么Google不让我们将属性定义为关键?而另一个是父母?然后我们可以命名它们并用作普通属性......

这里的最佳做法是什么?

Bry*_*utt 5

请记住,在GAE数据存储区中,您永远不能在创建实体后更改实体的父级或key_name.这些值对于实体的生命是永久性的.

如果Employee的account_name可能更改的可能性很小,则您不能将其用作key_name.如果它永远不会改变,那么它可能是一个非常好的key_name,并允许您使用Employee.get_by_key_name()代替昂贵的查询为Employees做便宜的获取.

父并不等同于外键.与外键相比更好的是引用属性.

使用父项的主要原因是父实体和子实体位于同一实体组中,允许您在单个事务中对它们进行操作.如果您只需要从Employee引用除法,那么只需使用引用属性.我建议熟悉实体组的工作方式,因为这对GAE数据建模非常重要:

使用父级也可能导致写入性能问题,因为写入单个实体组的速度有限(大约每秒一次写入).在决定是使用父属性还是引用属性时,您需要考虑在同一事务中需要修改哪些实体.在许多情况下,您可以使用Cross Group(XG)事务.这就是你要做出哪些权衡取舍.

所以我的建议是:

  • 如果员工的account_name绝对不会更改,则将其用作key_name.否则只需将它作为基本属性.
  • 如果您需要在同一事务中修改Employee和Division(并且您无法使其与XG事务一起使用),并且您永远不会更改Employee的Division,那么将该Division作为Employee的父级.否则只需使用引用属性建模此关系.