25

我知道有关实体组如何在 GAE 存储中工作的所有详细信息,但昨天(在帕洛阿尔托的 App Engine 聚会上),当一位演讲者解释他对实体组的使用时,我突然意识到我从未真正使用过它们在我自己的 GAE 应用程序中,我不记得在我使用过的开源 GAE 应用程序中看到它们。

所以,我怀疑我只是忽略了(没有注意到或记住)这样的例子,因为我根本不习惯它们,无法立即将“使用实体组”与“正在解决的应用程序问题类型”联系起来——而且我认为我应该通过研究这些资源来解决这个问题,重点关注 EG 使用正在解决的问题(即,为什么应用程序可以使用它,但没有它就无法工作或无法正常工作)。

任何人都可以建议此类代码的好 URL 吗?(论文也将受到欢迎,如果他们专注于应用程序级问题的解决,但如果像我所见过的大多数人一样,他们只关注 EG 如何工作的细节!-)。

4

3 回答 3

23

实体组的主要用途是提供在事务中更新多个实体的方法。

如果您不必使用它们,请数一数您的祝福。要么您一直在设计您的数据模型,因此没有两个实体需要同时更新以保持一致,或者您确实需要它们但您很幸运 :)

假设我有一个 Invoice 实体类型和一个 LineItem 实体类型。一张 Invoice 可以关联多个 LineItems。我的发票实体有一个名为 LastUpdated 的字段。每当 LineItem 添加到我的 Invoice 时,我都想将当前日期存储在 LastUpdated 字段中。

我的更新功能可能看起来像这样(伪代码)

invoice.lastUpdated = now()
lineitem = new lineitem()

invoice.put()
lineitem.put()

如果发票 put() 成功而 lineitem put() 失败会发生什么?我的发票日期将显示某些内容已更新,但实际更新(新 LineItem)将不存在。解决方案是将两个 puts() 都放在一个事务中。

另一种解决方案是使用查询来查找最后插入的 LineItem 的日期,而不是将此数据存储在 lastUpdated 字段中。但这将涉及每次您想知道最后一次添加订单项时都获取发票和所有订单项,从而花费您宝贵的数据存储配额。

编辑以回应海报的评论

啊。我想我理解你的困惑。上述段落说明了为什么交易很重要。但是您说您仍然不关心实体组,因为您看不到它们与事务的关系。但是,如果您使用的是 db.run-in-transaction,那么您正在使用实体组,也许您并没有意识到!每个事务只涉及一个且仅一个实体组,并且任何给定事务只能影响属于同一组的实体。看这里

“事务中的所有数据存储操作必须对同一实体组中的实体进行操作”。

您在交易中做了哪些事情?仅使用一个实体的交易有很多充分的理由,默认情况下,该实体位于其自己的实体组中。但有时您需要保持 2 个或更多实体同步,例如我上面的示例。如果 Invoice 和 LineItem Entities 不在同一个实体组中,那么您无法将对它们的修改包装在 db.run-in-transaction 调用中。因此,无论何时您想要对 2 个或更多实体进行事务操作,您都需要首先确保它们在同一个组中。希望这可以更清楚地说明它们为什么有用。

于 2009-07-09T17:08:06.357 回答
2

我在这里用过它们。我将我的客户对象设置为地图标记的父级。这为每个客户创建了一个实体组,并给了我两个优势:

  1. 获取客户的标记要快得多,因为它们与客户对象物理存储在一起。(在同一台服务器上,可能在同一磁盘上)

  2. 我可以在交易中更改客户的标记。我怀疑事务要求它们操作的所有对象都在同一个组中的原因是因为它们存储在同一个物理位置,这使得对数据实施锁定变得更加容易。

于 2009-07-10T08:12:12.473 回答
1

我在这个简单的 wiki 系统中使用了它们。页面的最新版本始终是根实体,过去的版本将最新版本作为祖先。复制操作在事务中完成,以保持版本一致性,避免在并发的情况下丢失版本。

于 2010-07-19T04:27:35.353 回答