根据我的理解,@ db.transactional(xg = True)允许跨组的事务,但是以下代码返回"事务内部的查询必须具有祖先"。
@db.transactional(xg=True)
def insertUserID(self,userName):
user = User.gql("WHERE userName = :1", userName).get()
highestUser = User.all().order('-userID').get()
nextUserID = highestID + 1
user.userID = nextUserID
user.put()
尽管是跨群组交易,您是否需要传递每个实体的密钥?你能帮忙修改这个例子吗?
答案 0 :(得分:2)
可以在max 25 entity个群组中应用XG交易。祖先查询将查询限制为单个实体组,您可以在单个XG事务中的这25个实体组中进行查询。
没有父级的事务性查询可能会包含应用程序中的所有实体组并锁定所有内容,因此您会收到错误消息。
在app引擎中,通常会尝试避免单调增加id。自动分配的可能类似于101,10001,10002等。如果你知道你需要单调增加它并且它对你有效,那么如何:
使用userId的某种模型表示来启用key_name 用法和直接查找
查询userId外部事务,获取最高候选人ID
在事务中执行get_or_insert;查找UserId.get_by_key_name(candidateid + 1)。如果 已存在并指向其他用户,请再次尝试使用+2 等等,直到找到一个免费的并创建它,更新 用户的userid属性。
如果更新UserId + User的XG事务太慢,可能在事务(而不是XG)中创建UserId +任务,然后让执行任务关联UserId和User。或者是一个可以序列化UserId创建的后端,如果你重新尝试避免序列中的漏洞并且每秒做50次创建,那么可能允许put_async。
如果可以将userName用作key_name,则可以直接查找而不是查询,从而使事情更快,更便宜。
答案 1 :(得分:1)
跨群组事务允许您跨多个组执行事务,但它们不会删除对事务内查询的禁止。您需要在事务外执行查询,并传入实体的ID(然后检查查询中指定的任何不变量仍然保留) - 或者,如Shay建议的那样,使用ID,这样您就不必进行查询首先。
答案 2 :(得分:1)
每个数据存储区实体都有一个密钥,一个密钥(其他数量的东西)有一个数字ID,AppEngine会为其分配或 key_name,您可以给它。
在你的情况下看起来你可以使用数字id,在你将拥有的用户实体上调用put()之后:user.key()。id()(或者user.key.id()如果你的使用NDB)对每个用户都是唯一的(只要所有用户都拥有相同的父代,在代码中为None)。
此ID不是连续的,但保证是唯一的。