GAE Datastore客户端:如何创建对属性实施强制唯一约束

时间:2018-12-25 11:49:55

标签: python-3.x google-app-engine google-cloud-datastore

我正在使用anom来映射GAE数据存储区实体。我正在寻找一种可扩展的方法来实现对属性的唯一约束。

到目前为止,在创建这样的新记录之前,我正在检查查询

class User(Model):
    ...
    email_id = props.String(indexed=True)
    ...

    def pre_put_hook(self):
        if (not self.id_or_name) and (User.query().where(User.email_id == self.email_id).count() > 0):
            raise IntegrityError(f'Duplicate entry: User.email == {self.email_id}')

它不处理竞争条件,也不会在数据库级别上强制唯一性。没有任何比赛条件,有没有办法做到这一点?

3 个答案:

答案 0 :(得分:2)

除了使用'email'作为您的主键do用户之外,没有什么好方法可以在数据库级别进行操作。您将依靠您的Web应用程序代码/ ORM(无论是anom还是ndb)执行该强制操作。

查看此答案

composite key in google cloud datastore

答案 1 :(得分:1)

当前方法仍然容易出现竞争条件的原因是,(非祖先)查询结果最终始终是一致的。即使您使用祖先查询(事务中唯一允许的查询),由于数据存储区的Isolation and consistency模型,您可能仍然面临竞争条件。

正如Alex所提到的,确保唯一性的唯一方法是将属性值用作实体的键标识符(您将在pre_put_hook方法中检查键的存在,请参见TypeError with get_or_insert) 。但是您只能对实体类型的单个属性执行此操作,尤其是对于电子邮件地址属性,这并不是一个好主意,因为很难处理电子邮件地址更改。

可能存在强制唯一性的方法,但允许出现临时/瞬态可能重复的条件,请参见ndb verify entity uniqueness in transaction

答案 2 :(得分:0)

我从webapp2的存储库中找到了此snippet,并为anom进行了修改 通过mixin轻松集成到任意数量的模型中。现在,我可以确认单个实体中多个字段的唯一性。当然,这在创建新记录时会遭受额外的读取,并且在更新时不会检查这些字段的唯一性。因此,尤其是在更新这些字段时,切勿允许更新这些字段或进行类似的检查。这是gist。我希望当使用新的GAE和anom作为数据映射器的Python 3运行时时,这将是有用的