我是 GAE 新手,对数据存储事务有一些疑问。
例如,我有一个用户实体,当用户在 Facebook 上添加我的应用程序时创建该实体。我通过 Facebook API 获得了一些属性,但我想为用户添加用户名,并且该用户名必须是唯一的。所以在事务范围内我调用这个方法:
def ExistsUsernameToDiferentUser(self, user, username):
query = User.all()
query.filter("username", username)
query.filter("idFacebook != ", user.idFacebook)
userReturned = query.get()
return True if userReturned else False
但 GAE 给了我这个错误:
BadRequestError:事务内的查询必须有祖先
好的,我明白,但是用户没有任何祖先,它是根实体。我需要做什么?
我明白你现在想做什么。
通过强制使用祖先,数据存储会强制您锁定数据存储的一部分(给定祖先下的所有内容),以便您可以保证该部分的一致性。然而,要做你想做的事,你本质上需要锁定所有 User 实体来查询某个 User 实体是否存在,然后创建一个新的 User 实体,然后解锁它们。
您可以这样做,只需创建一个实体,它可以是一个空实体,但确保它有一个唯一的键(如“用户祖先”),保存它,并使其成为每个用户实体的祖先。
这可能是一个坏主意,因为这会限制您在用户实体上的性能,特别是在写入方面。每次创建新用户时,都会阻止更新所有用户实体。
我试图说明在人力资源开发领域中您需要如何以不同的方式思考交易。您可以自行构建数据(使用祖先),以便为您的特定应用程序获得良好的性能特征。事实上,您可能不同意我的观点,并说用户实体的更新频率非常低,因此可以将它们全部锁定。
出于说明目的,另一种短视的可能性是根据用户名创建多个祖先。即,字母表中的每个字母对应一个。然后当你需要创建一个新的User时,你可以根据相应的祖先进行搜索。虽然这比拥有单一祖先有所改进(好 26 倍),但它仍然会预先限制您未来的表现。如果您现在知道最终将拥有的用户总数,这可能没问题,但我怀疑您需要数亿用户。
最好的方法是返回其他建议并将用户名作为密钥。这为您提供了最佳的可扩展性,因为通过密钥获取/设置用户实体可以是事务性的,并且不会锁定其他实体,从而限制您的可扩展性。
您需要找到一种方法来解决这个问题。例如,您在用户名之前获得的任何信息都可以存储在另一个实体中,该实体具有与稍后创建的用户相关的字段。或者,您可以在通过密钥创建用户实体后将该数据复制到用户实体中,然后删除原始实体。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)