您的理解是正确的:
-
您不能使用祖先查询,因为您的实体不在祖先关系中(即不在同一实体组中)。
-
不能在事务内执行非祖先查询。请注意,您在单个事务中读取的实体数也不能超过25个(每个实体位于单独的实体组中)。从…起
Restrictions on queries
:
事务内的查询必须是祖先查询
云数据存储
transactions
对属于up的实体进行操作
至25
entity groups
,但事务内部的查询必须
祖先查询。在事务中执行的所有查询必须
specify an ancestor
. 有关更多信息,请参阅
Datastore
Transactions
.
在与您类似的上下文中,典型的方法是在事务之外执行查询,通常只是
keys only
查询-获取实体键,然后通过在事务内进行键查找来读取相应的实体(一次最多25个)。并仅在绝对需要时使用事务,例如,请参阅以下相关讨论:
Ancestor relation in datastore
.
您的问题显然表明您正在以关系数据库的心态来处理数据存储。如果你的应用程序基本上需要关系数据(你没有描述你要做什么),数据存储
可以
不是最好的产品。看见
Choosing a storage option
. 我并不是说你不能将数据存储与关系数据一起使用,在许多情况下仍然可以这样做,但需要更仔细的设计-这些限制正在推动基于可伸缩数据存储的应用程序(IMHO可能比使用关系数据库实现的可伸缩性要高得多)
构建数据RDB样式(对于数据存储来说可以)和在RDB样式中使用数据RDB样式(不太好)之间存在差异。
在您提到的特定使用场景中,您不需要查询
sponsor
的
relationship
:您已经拥有
赞助商
的键
关系
实体,您所需要做的就是通过键查找它,这可以在事务中完成。
获取全部
关系
a的实体
person
需要一个查询,由
人
成为
赞助商
或者
sponsee
. 但这真的必须在交易中完成吗?或者如果你错过了结果列表a,这是可以接受的吗
关系
几秒钟前创建的?或者有一个最近被删除了?如果稍后再重复查询,它最终会(dis)出现在列表中(请参见
Eventual Consistency on Reading an Index
). 如果这是可以接受的(依我看,关系不会经常更改,在更改后立即进行查询的可能性很小),那么您不需要在事务中进行查询,因此您不需要在
people
和
关系
实体。非常适合扩展性。
另一个考虑因素:循环浏览
关系
实体:也不一定必须在事务中完成。而且,如果关系的数量很大,循环可能会到达请求截止日期。一种更具可扩展性的方法是使用查询游标并将工作拆分为多个任务/请求,每个任务/请求处理列表的一个子集。请参见此类方法的Python示例:
How to delete all the entries from google datastore?
对于每个
人
删除案例:
-
添加类似于
being_deleted
(在交易中)的财产
人
标记删除并防止在删除过程中使用,例如在执行删除任务时创建新关系。在应用程序逻辑中(也在事务中)需要的任何位置添加此标志的检查。
-
获取所有列表
关系
并使用上述循环技术将其删除
-
在最后一个循环迭代中,当没有关系剩下时,将另一个任务排入队列(大量延迟),以重新检查在前一个循环执行中可能由于最终一致性而错过的任何最近的关系。如果有显示,请重新运行循环,否则只需删除
人
如果不考虑可伸缩性,还可以重新设计数据结构,以便在所有实体之间使用祖先(将它们放在同一个实体组中),然后可以做您想要的事情。例如,参见,
What would be the purpose of putting all datastore entities in a single group?
. 但有许多潜在风险需要注意,例如: